diff --git a/src/Makefile.am b/src/Makefile.am index ad85a81b..081430f7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,7 +58,6 @@ librcldir = $(libdir)/recoll librcl_LTLIBRARIES = librecoll.la librecoll_la_SOURCES = \ -aspell/aspell-local.h \ aspell/rclaspell.cpp \ aspell/rclaspell.h \ bincimapmime/convert.cc \ diff --git a/src/aspell/aspell-local.h b/src/aspell/aspell-local.h deleted file mode 100644 index 421c9380..00000000 --- a/src/aspell/aspell-local.h +++ /dev/null @@ -1,729 +0,0 @@ -/* Automatically generated file. Do not edit directly. */ - -/* This file is part of The New Aspell - * Copyright (C) 2001-2002 by Kevin Atkinson under the GNU LGPL - * license version 2.0 or 2.1. You should have received a copy of the - * LGPL license along with this library if you did not you can find it - * at http://www.gnu.org/. */ - -#ifndef ASPELL_ASPELL__H -#define ASPELL_ASPELL__H - -#ifdef __cplusplus -extern "C" { -#endif - -/******************************* type id *******************************/ - - -union AspellTypeId { - - unsigned int num; - - char str[4]; - -}; - - -typedef union AspellTypeId AspellTypeId; - - -/************************** mutable container **************************/ - - -typedef struct AspellMutableContainer AspellMutableContainer; - - -int aspell_mutable_container_add(struct AspellMutableContainer * ths, const char * to_add); - -int aspell_mutable_container_remove(struct AspellMutableContainer * ths, const char * to_rem); - -void aspell_mutable_container_clear(struct AspellMutableContainer * ths); - -struct AspellMutableContainer * aspell_mutable_container_to_mutable_container(struct AspellMutableContainer * ths); - - - -/******************************* key info *******************************/ - - - -enum AspellKeyInfoType {AspellKeyInfoString, AspellKeyInfoInt, AspellKeyInfoBool, AspellKeyInfoList}; -typedef enum AspellKeyInfoType AspellKeyInfoType; - - -struct AspellKeyInfo { - - /* The name of the key. */ - const char * name; - - /* The key type. */ - enum AspellKeyInfoType type; - - /* The default value of the key. */ - const char * def; - - /* A brief description of the key or NULL if internal value. */ - const char * desc; - - int flags; - - int other_data; - -}; - - -typedef struct AspellKeyInfo AspellKeyInfo; - - -/******************************** config ********************************/ - - -typedef struct AspellKeyInfoEnumeration AspellKeyInfoEnumeration; - - -int aspell_key_info_enumeration_at_end(const struct AspellKeyInfoEnumeration * ths); - -const struct AspellKeyInfo * aspell_key_info_enumeration_next(struct AspellKeyInfoEnumeration * ths); - -void delete_aspell_key_info_enumeration(struct AspellKeyInfoEnumeration * ths); - -struct AspellKeyInfoEnumeration * aspell_key_info_enumeration_clone(const struct AspellKeyInfoEnumeration * ths); - -void aspell_key_info_enumeration_assign(struct AspellKeyInfoEnumeration * ths, const struct AspellKeyInfoEnumeration * other); - - - -typedef struct AspellConfig AspellConfig; - - -struct AspellConfig * new_aspell_config(); - -void delete_aspell_config(struct AspellConfig * ths); - -struct AspellConfig * aspell_config_clone(const struct AspellConfig * ths); - -void aspell_config_assign(struct AspellConfig * ths, const struct AspellConfig * other); - -unsigned int aspell_config_error_number(const struct AspellConfig * ths); - -const char * aspell_config_error_message(const struct AspellConfig * ths); - -const struct AspellError * aspell_config_error(const struct AspellConfig * ths); - -/* Sets extra keys which this config class should - * accept. begin and end are expected to point to - * the beginning and ending of an array of Aspell - * Key Info. */ -void aspell_config_set_extra(struct AspellConfig * ths, const struct AspellKeyInfo * begin, const struct AspellKeyInfo * end); - -/* Returns the KeyInfo object for the - * corresponding key or returns NULL and sets - * error_num to PERROR_UNKNOWN_KEY if the key is - * not valid. The pointer returned is valid for - * the lifetime of the object. */ -const struct AspellKeyInfo * aspell_config_keyinfo(struct AspellConfig * ths, const char * key); - -/* Returns a newly allocated enumeration of all - * the possible objects this config class uses. */ -struct AspellKeyInfoEnumeration * aspell_config_possible_elements(struct AspellConfig * ths, int include_extra); - -/* Returns the default value for given key which - * may involve substituting variables, thus it is - * not the same as keyinfo(key)->def returns NULL - * and sets error_num to PERROR_UNKNOWN_KEY if - * the key is not valid. Uses the temporary - * string. */ -const char * aspell_config_get_default(struct AspellConfig * ths, const char * key); - -/* Returns a newly allocated enumeration of all - * the key/value pairs. This DOES not include ones - * which are set to their default values. */ -struct AspellStringPairEnumeration * aspell_config_elements(struct AspellConfig * ths); - -/* Inserts an item, if the item already exists it - * will be replaced. Returns TRUE if it succeeded - * or FALSE on error. If the key in not valid it - * sets error_num to PERROR_UNKNOWN_KEY, if the - * value is not valid it will set error_num to - * PERROR_BAD_VALUE, if the value can not be - * changed it sets error_num to - * PERROR_CANT_CHANGE_VALUE, and if the value is - * a list and you are trying to set its directory, - * it sets error_num to PERROR_LIST_SET */ -int aspell_config_replace(struct AspellConfig * ths, const char * key, const char * value); - -/* Remove a key and returns TRUE if it exists - * otherwise return FALSE. This effectively sets - * the key to its default value. Calling replace - * with a value of "" will also call - * remove. If the key does not exist then it sets - * error_num to 0 or PERROR_NOT, if the key is - * not valid then it sets error_num to - * PERROR_UNKNOWN_KEY, if the value can not be - * changed then it sets error_num to - * PERROR_CANT_CHANGE_VALUE */ -int aspell_config_remove(struct AspellConfig * ths, const char * key); - -int aspell_config_have(const struct AspellConfig * ths, const char * key); - -/* Returns NULL on error. */ -const char * aspell_config_retrieve(struct AspellConfig * ths, const char * key); - -int aspell_config_retrieve_list(struct AspellConfig * ths, const char * key, struct AspellMutableContainer * lst); - -/* Return -1 on error, 0 if false, 1 if true. */ -int aspell_config_retrieve_bool(struct AspellConfig * ths, const char * key); - -/* Return -1 on error. */ -int aspell_config_retrieve_int(struct AspellConfig * ths, const char * key); - - - -/******************************** error ********************************/ - - -struct AspellError { - - const char * mesg; - - const struct AspellErrorInfo * err; - -}; - - -typedef struct AspellError AspellError; - -int aspell_error_is_a(const struct AspellError * ths, const struct AspellErrorInfo * e); - - -struct AspellErrorInfo { - - const struct AspellErrorInfo * isa; - - const char * mesg; - - unsigned int num_parms; - - const char * parms[3]; - -}; - - -typedef struct AspellErrorInfo AspellErrorInfo; - - -/**************************** can have error ****************************/ - - -typedef struct AspellCanHaveError AspellCanHaveError; - - -unsigned int aspell_error_number(const struct AspellCanHaveError * ths); - -const char * aspell_error_message(const struct AspellCanHaveError * ths); - -const struct AspellError * aspell_error(const struct AspellCanHaveError * ths); - -void delete_aspell_can_have_error(struct AspellCanHaveError * ths); - - - -/******************************** errors ********************************/ - - -extern const struct AspellErrorInfo * const aerror_other; -extern const struct AspellErrorInfo * const aerror_operation_not_supported; -extern const struct AspellErrorInfo * const aerror_cant_copy; -extern const struct AspellErrorInfo * const aerror_unimplemented_method; -extern const struct AspellErrorInfo * const aerror_file; -extern const struct AspellErrorInfo * const aerror_cant_open_file; -extern const struct AspellErrorInfo * const aerror_cant_read_file; -extern const struct AspellErrorInfo * const aerror_cant_write_file; -extern const struct AspellErrorInfo * const aerror_invalid_name; -extern const struct AspellErrorInfo * const aerror_bad_file_format; -extern const struct AspellErrorInfo * const aerror_dir; -extern const struct AspellErrorInfo * const aerror_cant_read_dir; -extern const struct AspellErrorInfo * const aerror_config; -extern const struct AspellErrorInfo * const aerror_unknown_key; -extern const struct AspellErrorInfo * const aerror_cant_change_value; -extern const struct AspellErrorInfo * const aerror_bad_key; -extern const struct AspellErrorInfo * const aerror_bad_value; -extern const struct AspellErrorInfo * const aerror_duplicate; -extern const struct AspellErrorInfo * const aerror_key_not_string; -extern const struct AspellErrorInfo * const aerror_key_not_int; -extern const struct AspellErrorInfo * const aerror_key_not_bool; -extern const struct AspellErrorInfo * const aerror_key_not_list; -extern const struct AspellErrorInfo * const aerror_no_value_reset; -extern const struct AspellErrorInfo * const aerror_no_value_enable; -extern const struct AspellErrorInfo * const aerror_no_value_disable; -extern const struct AspellErrorInfo * const aerror_no_value_clear; -extern const struct AspellErrorInfo * const aerror_language_related; -extern const struct AspellErrorInfo * const aerror_unknown_language; -extern const struct AspellErrorInfo * const aerror_unknown_soundslike; -extern const struct AspellErrorInfo * const aerror_language_not_supported; -extern const struct AspellErrorInfo * const aerror_no_wordlist_for_lang; -extern const struct AspellErrorInfo * const aerror_mismatched_language; -extern const struct AspellErrorInfo * const aerror_affix; -extern const struct AspellErrorInfo * const aerror_corrupt_affix; -extern const struct AspellErrorInfo * const aerror_invalid_cond; -extern const struct AspellErrorInfo * const aerror_invalid_cond_strip; -extern const struct AspellErrorInfo * const aerror_incorrect_encoding; -extern const struct AspellErrorInfo * const aerror_encoding; -extern const struct AspellErrorInfo * const aerror_unknown_encoding; -extern const struct AspellErrorInfo * const aerror_encoding_not_supported; -extern const struct AspellErrorInfo * const aerror_conversion_not_supported; -extern const struct AspellErrorInfo * const aerror_pipe; -extern const struct AspellErrorInfo * const aerror_cant_create_pipe; -extern const struct AspellErrorInfo * const aerror_process_died; -extern const struct AspellErrorInfo * const aerror_bad_input; -extern const struct AspellErrorInfo * const aerror_invalid_string; -extern const struct AspellErrorInfo * const aerror_invalid_word; -extern const struct AspellErrorInfo * const aerror_invalid_affix; -extern const struct AspellErrorInfo * const aerror_inapplicable_affix; -extern const struct AspellErrorInfo * const aerror_unknown_unichar; -extern const struct AspellErrorInfo * const aerror_word_list_flags; -extern const struct AspellErrorInfo * const aerror_invalid_flag; -extern const struct AspellErrorInfo * const aerror_conflicting_flags; -extern const struct AspellErrorInfo * const aerror_version_control; -extern const struct AspellErrorInfo * const aerror_bad_version_string; -extern const struct AspellErrorInfo * const aerror_filter; -extern const struct AspellErrorInfo * const aerror_cant_dlopen_file; -extern const struct AspellErrorInfo * const aerror_empty_filter; -extern const struct AspellErrorInfo * const aerror_no_such_filter; -extern const struct AspellErrorInfo * const aerror_confusing_version; -extern const struct AspellErrorInfo * const aerror_bad_version; -extern const struct AspellErrorInfo * const aerror_identical_option; -extern const struct AspellErrorInfo * const aerror_options_only; -extern const struct AspellErrorInfo * const aerror_invalid_option_modifier; -extern const struct AspellErrorInfo * const aerror_cant_describe_filter; -extern const struct AspellErrorInfo * const aerror_filter_mode_file; -extern const struct AspellErrorInfo * const aerror_mode_option_name; -extern const struct AspellErrorInfo * const aerror_no_filter_to_option; -extern const struct AspellErrorInfo * const aerror_bad_mode_key; -extern const struct AspellErrorInfo * const aerror_expect_mode_key; -extern const struct AspellErrorInfo * const aerror_mode_version_requirement; -extern const struct AspellErrorInfo * const aerror_confusing_mode_version; -extern const struct AspellErrorInfo * const aerror_bad_mode_version; -extern const struct AspellErrorInfo * const aerror_missing_magic_expression; -extern const struct AspellErrorInfo * const aerror_empty_file_ext; -extern const struct AspellErrorInfo * const aerror_filter_mode_expand; -extern const struct AspellErrorInfo * const aerror_unknown_mode; -extern const struct AspellErrorInfo * const aerror_mode_extend_expand; -extern const struct AspellErrorInfo * const aerror_filter_mode_magic; -extern const struct AspellErrorInfo * const aerror_file_magic_pos; -extern const struct AspellErrorInfo * const aerror_file_magic_range; -extern const struct AspellErrorInfo * const aerror_missing_magic; -extern const struct AspellErrorInfo * const aerror_bad_magic; -extern const struct AspellErrorInfo * const aerror_expression; -extern const struct AspellErrorInfo * const aerror_invalid_expression; - - -/******************************* speller *******************************/ - - -typedef struct AspellSpeller AspellSpeller; - - -struct AspellCanHaveError * new_aspell_speller(struct AspellConfig * config); - -struct AspellSpeller * to_aspell_speller(struct AspellCanHaveError * obj); - -void delete_aspell_speller(struct AspellSpeller * ths); - -unsigned int aspell_speller_error_number(const struct AspellSpeller * ths); - -const char * aspell_speller_error_message(const struct AspellSpeller * ths); - -const struct AspellError * aspell_speller_error(const struct AspellSpeller * ths); - -struct AspellConfig * aspell_speller_config(struct AspellSpeller * ths); - -/* Returns 0 if it is not in the dictionary, - * 1 if it is, or -1 on error. */ -int aspell_speller_check(struct AspellSpeller * ths, const char * word, int word_size); - -/* Add this word to your own personal word list. */ -int aspell_speller_add_to_personal(struct AspellSpeller * ths, const char * word, int word_size); - -/* Add this word to the current spelling session. */ -int aspell_speller_add_to_session(struct AspellSpeller * ths, const char * word, int word_size); - -/* This is your own personal word list file plus - * any extra words added during this session to - * your own personal word list. */ -const struct AspellWordList * aspell_speller_personal_word_list(struct AspellSpeller * ths); - -/* This is a list of words added to this session - * that are not in the main word list or in your - * own personal list but are considered valid for - * this spelling session. */ -const struct AspellWordList * aspell_speller_session_word_list(struct AspellSpeller * ths); - -/* This is the main list of words used during this - * spelling session. */ -const struct AspellWordList * aspell_speller_main_word_list(struct AspellSpeller * ths); - -int aspell_speller_save_all_word_lists(struct AspellSpeller * ths); - -int aspell_speller_clear_session(struct AspellSpeller * ths); - -/* Return NULL on error. - * The word list returned by suggest is only - * valid until the next call to suggest. */ -const struct AspellWordList * aspell_speller_suggest(struct AspellSpeller * ths, const char * word, int word_size); - -int aspell_speller_store_replacement(struct AspellSpeller * ths, const char * mis, int mis_size, const char * cor, int cor_size); - - - -/******************************** filter ********************************/ - - -typedef struct AspellFilter AspellFilter; - - -void delete_aspell_filter(struct AspellFilter * ths); - -unsigned int aspell_filter_error_number(const struct AspellFilter * ths); - -const char * aspell_filter_error_message(const struct AspellFilter * ths); - -const struct AspellError * aspell_filter_error(const struct AspellFilter * ths); - -struct AspellFilter * to_aspell_filter(struct AspellCanHaveError * obj); - - - -/*************************** document checker ***************************/ - - -struct AspellToken { - - unsigned int offset; - - unsigned int len; - -}; - - -typedef struct AspellToken AspellToken; - - -typedef struct AspellDocumentChecker AspellDocumentChecker; - - -void delete_aspell_document_checker(struct AspellDocumentChecker * ths); - -unsigned int aspell_document_checker_error_number(const struct AspellDocumentChecker * ths); - -const char * aspell_document_checker_error_message(const struct AspellDocumentChecker * ths); - -const struct AspellError * aspell_document_checker_error(const struct AspellDocumentChecker * ths); - -/* Creates a new document checker. - * The speller class is expected to last until - * this class is destroyed. - * If config is given it will be used to override - * any relevent options set by this speller class. - * The config class is not once this function is done. - * If filter is given then it will take ownership of - * the filter class and use it to do the filtering. - * You are expected to free the checker when done. */ -struct AspellCanHaveError * new_aspell_document_checker(struct AspellSpeller * speller); - -struct AspellDocumentChecker * to_aspell_document_checker(struct AspellCanHaveError * obj); - -/* Reset the internal state of the filter. - * Should be called whenever a new document is - * being filtered. */ -void aspell_document_checker_reset(struct AspellDocumentChecker * ths); - -/* Process a string. - * The string passed in should only be split on - * white space characters. Furthermore, between - * calls to reset, each string should be passed - * in exactly once and in the order they appeared - * in the document. Passing in strings out of - * order, skipping strings or passing them in - * more than once may lead to undefined results. */ -void aspell_document_checker_process(struct AspellDocumentChecker * ths, const char * str, int size); - -/* Returns the next misspelled word in the - * processed string. If there are no more - * misspelled words, then token.word will be - * NULL and token.size will be 0 */ -struct AspellToken aspell_document_checker_next_misspelling(struct AspellDocumentChecker * ths); - -/* Returns the underlying filter class. */ -struct AspellFilter * aspell_document_checker_filter(struct AspellDocumentChecker * ths); - - - -/****************************** word list ******************************/ - - -typedef struct AspellWordList AspellWordList; - - -int aspell_word_list_empty(const struct AspellWordList * ths); - -unsigned int aspell_word_list_size(const struct AspellWordList * ths); - -struct AspellStringEnumeration * aspell_word_list_elements(const struct AspellWordList * ths); - - - -/************************** string enumeration **************************/ - - -typedef struct AspellStringEnumeration AspellStringEnumeration; - - -void delete_aspell_string_enumeration(struct AspellStringEnumeration * ths); - -struct AspellStringEnumeration * aspell_string_enumeration_clone(const struct AspellStringEnumeration * ths); - -void aspell_string_enumeration_assign(struct AspellStringEnumeration * ths, const struct AspellStringEnumeration * other); - -int aspell_string_enumeration_at_end(const struct AspellStringEnumeration * ths); - -const char * aspell_string_enumeration_next(struct AspellStringEnumeration * ths); - - - -/********************************* info *********************************/ - - -struct AspellModuleInfo { - - const char * name; - - double order_num; - - const char * lib_dir; - - struct AspellStringList * dict_dirs; - - struct AspellStringList * dict_exts; - -}; - - -typedef struct AspellModuleInfo AspellModuleInfo; - - -struct AspellDictInfo { - - /* The Name to identify this dictionary by. */ - const char * name; - - /* The language code to identify this dictionary. - * A two letter UPPER-CASE ISO 639 language code - * and an optional two letter ISO 3166 country - * code after a dash or underscore. */ - const char * code; - - /* Any extra information to distinguish this - * variety of dictionary from other dictionaries - * which may have the same language and size. */ - const char * jargon; - - int size; - - /* A two char digit code describing the size of - * the dictionary: 10=tiny, 20=really small, - * 30=small, 40=med-small, 50=med, 60=med-large, - * 70=large, 80=huge, 90=insane. Please check - * the README in aspell-lang-200?????.tar.bz2 or - * see SCOWL (http://wordlist.sourceforge.net) - * for an example of how these sizes are used. */ - const char * size_str; - - struct AspellModuleInfo * module; - -}; - - -typedef struct AspellDictInfo AspellDictInfo; - - -typedef struct AspellModuleInfoList AspellModuleInfoList; - - -struct AspellModuleInfoList * get_aspell_module_info_list(struct AspellConfig * config); - -int aspell_module_info_list_empty(const struct AspellModuleInfoList * ths); - -unsigned int aspell_module_info_list_size(const struct AspellModuleInfoList * ths); - -struct AspellModuleInfoEnumeration * aspell_module_info_list_elements(const struct AspellModuleInfoList * ths); - - - -typedef struct AspellDictInfoList AspellDictInfoList; - - -struct AspellDictInfoList * get_aspell_dict_info_list(struct AspellConfig * config); - -int aspell_dict_info_list_empty(const struct AspellDictInfoList * ths); - -unsigned int aspell_dict_info_list_size(const struct AspellDictInfoList * ths); - -struct AspellDictInfoEnumeration * aspell_dict_info_list_elements(const struct AspellDictInfoList * ths); - - - -typedef struct AspellModuleInfoEnumeration AspellModuleInfoEnumeration; - - -int aspell_module_info_enumeration_at_end(const struct AspellModuleInfoEnumeration * ths); - -const struct AspellModuleInfo * aspell_module_info_enumeration_next(struct AspellModuleInfoEnumeration * ths); - -void delete_aspell_module_info_enumeration(struct AspellModuleInfoEnumeration * ths); - -struct AspellModuleInfoEnumeration * aspell_module_info_enumeration_clone(const struct AspellModuleInfoEnumeration * ths); - -void aspell_module_info_enumeration_assign(struct AspellModuleInfoEnumeration * ths, const struct AspellModuleInfoEnumeration * other); - - - -typedef struct AspellDictInfoEnumeration AspellDictInfoEnumeration; - - -int aspell_dict_info_enumeration_at_end(const struct AspellDictInfoEnumeration * ths); - -const struct AspellDictInfo * aspell_dict_info_enumeration_next(struct AspellDictInfoEnumeration * ths); - -void delete_aspell_dict_info_enumeration(struct AspellDictInfoEnumeration * ths); - -struct AspellDictInfoEnumeration * aspell_dict_info_enumeration_clone(const struct AspellDictInfoEnumeration * ths); - -void aspell_dict_info_enumeration_assign(struct AspellDictInfoEnumeration * ths, const struct AspellDictInfoEnumeration * other); - - - -/***************************** string list *****************************/ - - -typedef struct AspellStringList AspellStringList; - - -struct AspellStringList * new_aspell_string_list(); - -int aspell_string_list_empty(const struct AspellStringList * ths); - -unsigned int aspell_string_list_size(const struct AspellStringList * ths); - -struct AspellStringEnumeration * aspell_string_list_elements(const struct AspellStringList * ths); - -int aspell_string_list_add(struct AspellStringList * ths, const char * to_add); - -int aspell_string_list_remove(struct AspellStringList * ths, const char * to_rem); - -void aspell_string_list_clear(struct AspellStringList * ths); - -struct AspellMutableContainer * aspell_string_list_to_mutable_container(struct AspellStringList * ths); - -void delete_aspell_string_list(struct AspellStringList * ths); - -struct AspellStringList * aspell_string_list_clone(const struct AspellStringList * ths); - -void aspell_string_list_assign(struct AspellStringList * ths, const struct AspellStringList * other); - - - -/****************************** string map ******************************/ - - -typedef struct AspellStringMap AspellStringMap; - - -struct AspellStringMap * new_aspell_string_map(); - -int aspell_string_map_add(struct AspellStringMap * ths, const char * to_add); - -int aspell_string_map_remove(struct AspellStringMap * ths, const char * to_rem); - -void aspell_string_map_clear(struct AspellStringMap * ths); - -struct AspellMutableContainer * aspell_string_map_to_mutable_container(struct AspellStringMap * ths); - -void delete_aspell_string_map(struct AspellStringMap * ths); - -struct AspellStringMap * aspell_string_map_clone(const struct AspellStringMap * ths); - -void aspell_string_map_assign(struct AspellStringMap * ths, const struct AspellStringMap * other); - -int aspell_string_map_empty(const struct AspellStringMap * ths); - -unsigned int aspell_string_map_size(const struct AspellStringMap * ths); - -struct AspellStringPairEnumeration * aspell_string_map_elements(const struct AspellStringMap * ths); - -/* Insert a new element. - * Will NOT overwrite an existing entry. - * Returns FALSE if the element already exists. */ -int aspell_string_map_insert(struct AspellStringMap * ths, const char * key, const char * value); - -/* Insert a new element. - * Will overwrite an existing entry. - * Always returns TRUE. */ -int aspell_string_map_replace(struct AspellStringMap * ths, const char * key, const char * value); - -/* Looks up an element and returns the value. - * Returns NULL if the element does not exist. - * Returns an empty string if the element exists - * but has a NULL value. */ -const char * aspell_string_map_lookup(const struct AspellStringMap * ths, const char * key); - - - -/***************************** string pair *****************************/ - - -struct AspellStringPair { - - const char * first; - - const char * second; - -}; - - -typedef struct AspellStringPair AspellStringPair; - - -/*********************** string pair enumeration ***********************/ - - -typedef struct AspellStringPairEnumeration AspellStringPairEnumeration; - - -int aspell_string_pair_enumeration_at_end(const struct AspellStringPairEnumeration * ths); - -struct AspellStringPair aspell_string_pair_enumeration_next(struct AspellStringPairEnumeration * ths); - -void delete_aspell_string_pair_enumeration(struct AspellStringPairEnumeration * ths); - -struct AspellStringPairEnumeration * aspell_string_pair_enumeration_clone(const struct AspellStringPairEnumeration * ths); - -void aspell_string_pair_enumeration_assign(struct AspellStringPairEnumeration * ths, const struct AspellStringPairEnumeration * other); - - - -/******************************** cache ********************************/ - - -/* Reset the global cache(s) so that cache queries will - * create a new object. If existing objects are still in - * use they are not deleted. If which is NULL then all - * caches will be reset. Current caches are "encode", - * "decode", "dictionary", "language", and "keyboard". */ -int aspell_reset_cache(const char * which); - -#ifdef __cplusplus -} -#endif -#endif /* ASPELL_ASPELL__H */ diff --git a/src/aspell/rclaspell.cpp b/src/aspell/rclaspell.cpp index 818e03c9..73230ed6 100644 --- a/src/aspell/rclaspell.cpp +++ b/src/aspell/rclaspell.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006-2019 J.F.Dockes +/* Copyright (C) 2006-2021 J.F.Dockes * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -18,8 +18,6 @@ #ifdef RCL_USE_ASPELL -#include ASPELL_INCLUDE - #include #include @@ -34,72 +32,11 @@ using namespace std; -// Aspell library entry points -class AspellApi { -public: - struct AspellConfig *(*new_aspell_config)(); - int (*aspell_config_replace)(struct AspellConfig *, const char * key, - const char * value); - struct AspellCanHaveError *(*new_aspell_speller)(struct AspellConfig *); - void (*delete_aspell_config)(struct AspellConfig *); - void (*delete_aspell_can_have_error)(struct AspellCanHaveError *); - struct AspellSpeller * (*to_aspell_speller)(struct AspellCanHaveError *); - struct AspellConfig * (*aspell_speller_config)(struct AspellSpeller *); - const struct AspellWordList * (*aspell_speller_suggest) - (struct AspellSpeller *, const char *, int); - int (*aspell_speller_check)(struct AspellSpeller *, const char *, int); - struct AspellStringEnumeration * (*aspell_word_list_elements) - (const struct AspellWordList * ths); - const char * (*aspell_string_enumeration_next) - (struct AspellStringEnumeration * ths); - void (*delete_aspell_string_enumeration)(struct AspellStringEnumeration *); - const struct AspellError *(*aspell_error) - (const struct AspellCanHaveError *); - const char *(*aspell_error_message)(const struct AspellCanHaveError *); - const char *(*aspell_speller_error_message)(const struct AspellSpeller *); - void (*delete_aspell_speller)(struct AspellSpeller *); - -}; -static AspellApi aapi; -static std::mutex o_aapi_mutex; - -#define NMTOPTR(NM, TP) \ - if ((aapi.NM = TP dlib_sym(m_data->m_handle, #NM)) == 0) { \ - badnames += #NM + string(" "); \ - } - -static const vector aspell_lib_suffixes { -#if defined(__APPLE__) - ".15.dylib", - ".dylib", -#elif defined(_WIN32) - "-15.dll", -#else - ".so", - ".so.15", -#endif -}; - // Private rclaspell data class AspellData { public: - ~AspellData() { - LOGDEB2("~AspellData\n" ); - if (m_handle) { - dlib_close(m_handle); - m_handle = nullptr; - } - if (m_speller) { - // Dumps core if I do this?? - //aapi.delete_aspell_speller(m_speller); - m_speller = nullptr; - LOGDEB2("~AspellData: speller done\n" ); - } - } - - void *m_handle{nullptr}; string m_exec; - AspellSpeller *m_speller{nullptr}; + ExecCmd m_speller; #ifdef _WIN32 string m_datadir; #endif @@ -118,7 +55,6 @@ Aspell::~Aspell() bool Aspell::init(string &reason) { - std::unique_lock locker(o_aapi_mutex); deleteZ(m_data); // Language: we get this from the configuration, else from the NLS @@ -149,11 +85,10 @@ bool Aspell::init(string &reason) m_config->getConfParam("aspellAddCreateParam", m_data->m_addCreateParam); #ifdef _WIN32 m_data->m_datadir = path_cat( - path_pkgdatadir(), - "filters/aspell-installed/mingw32/lib/aspell-0.60"); + path_pkgdatadir(), "filters/aspell-installed/mingw32/lib/aspell-0.60"); if (m_data->m_addCreateParam.empty()) { - m_data->m_addCreateParam = string("--local-data-dir=") + - path_cat(m_config->getConfDir(), "aspell"); + m_data->m_addCreateParam = + string("--local-data-dir=") + path_cat(m_config->getConfDir(), "aspell"); } #endif // WIN32 @@ -179,110 +114,16 @@ bool Aspell::init(string &reason) return false; } - // Don't know what with Apple and (DY)LD_LIBRARY_PATH. Does not work - // So we look in all ../lib in the PATH... -#if defined(__APPLE__) - vector path; - const char *pp = getenv("PATH"); - if (pp) { - stringToTokens(pp, path, ":"); - } -#endif - - reason = "Could not open shared library "; - string libbase("libaspell"); - string lib; - for (const auto& suff : aspell_lib_suffixes) { - lib = libbase + suff; - reason += string("[") + lib + "] "; - if ((m_data->m_handle = dlib_open(lib)) != 0) { - reason.erase(); - goto found; - } - // Above was the normal lookup: let dlopen search the directories. - // Also look in other places for Apple and Windows. -#if defined(__APPLE__) - for (const auto& dir : path) { - string lib1 = path_canon(dir + "/../lib/" + lib); - if ((m_data->m_handle = dlib_open(lib1)) != 0) { - reason.erase(); - lib=lib1; - goto found; - } - } -#endif -#if defined(_WIN32) && !defined(_MSC_VER) - // Look in the directory of the aspell binary. When building - // with msvc, the aspell .exe is still the mingw one, but we - // copy the msvc dll in the recoll top directory, so no need - // to look in the aspell one. - { - string bindir = path_getfather(m_data->m_exec); - string lib1 = path_cat(bindir, lib); - if ((m_data->m_handle = dlib_open(lib1)) != 0) { - reason.erase(); - lib=lib1; - goto found; - } - } -#endif - } - -found: - if (m_data->m_handle == 0) { - reason += string(" : ") + dlib_error(); - deleteZ(m_data); - return false; - } - - string badnames; - NMTOPTR(new_aspell_config, (struct AspellConfig *(*)())); - NMTOPTR(aspell_config_replace, (int (*)(struct AspellConfig *, - const char *, const char *))); - NMTOPTR(new_aspell_speller, - (struct AspellCanHaveError *(*)(struct AspellConfig *))); - NMTOPTR(delete_aspell_config, - (void (*)(struct AspellConfig *))); - NMTOPTR(delete_aspell_can_have_error, - (void (*)(struct AspellCanHaveError *))); - NMTOPTR(to_aspell_speller, - (struct AspellSpeller *(*)(struct AspellCanHaveError *))); - NMTOPTR(aspell_speller_config, - (struct AspellConfig *(*)(struct AspellSpeller *))); - NMTOPTR(aspell_speller_suggest, - (const struct AspellWordList *(*)(struct AspellSpeller *, - const char *, int))); - NMTOPTR(aspell_speller_check, - (int (*)(struct AspellSpeller *, const char *, int))); - NMTOPTR(aspell_word_list_elements, - (struct AspellStringEnumeration *(*) - (const struct AspellWordList *))); - NMTOPTR(aspell_string_enumeration_next, - (const char * (*)(struct AspellStringEnumeration *))); - NMTOPTR(delete_aspell_string_enumeration, - (void (*)(struct AspellStringEnumeration *))); - NMTOPTR(aspell_error, - (const struct AspellError*(*)(const struct AspellCanHaveError *))); - NMTOPTR(aspell_error_message, - (const char *(*)(const struct AspellCanHaveError *))); - NMTOPTR(aspell_speller_error_message, - (const char *(*)(const struct AspellSpeller *))); - NMTOPTR(delete_aspell_speller, (void (*)(struct AspellSpeller *))); - - if (!badnames.empty()) { - reason = string("Aspell::init: symbols not found:") + badnames; - deleteZ(m_data); - return false; - } - return true; } + bool Aspell::ok() const { - return m_data != 0 && m_data->m_handle != 0; + return nullptr != m_data; } + string Aspell::dicPath() { string ccdir = m_config->getAspellcacheDir(); @@ -409,84 +250,76 @@ bool Aspell::buildDict(Rcl::Db &db, string &reason) return true; } -static const unsigned int ldatadiroptsz = - string("--local-data-dir=").size(); +static const unsigned int ldatadiroptsz = strlen("--local-data-dir="); bool Aspell::make_speller(string& reason) { if (!ok()) return false; - if (m_data->m_speller != 0) + if (m_data->m_speller.getChildPid() > 0) return true; - AspellCanHaveError *ret; + // aspell --lang=[lang] --encoding=utf-8 --master=[dicPath()] --sug-mode=fast pipe + + string cmdstring(m_data->m_exec); + + ExecCmd aspell; + vector args; + + args.push_back(string("--lang=")+ m_lang); + cmdstring += string(" ") + args.back(); + + args.push_back("--encoding=utf-8"); + cmdstring += string(" ") + args.back(); - AspellConfig *config = aapi.new_aspell_config(); - aapi.aspell_config_replace(config, "lang", m_lang.c_str()); - aapi.aspell_config_replace(config, "encoding", "utf-8"); - aapi.aspell_config_replace(config, "master", dicPath().c_str()); - aapi.aspell_config_replace(config, "sug-mode", "fast"); #ifdef _WIN32 - aapi.aspell_config_replace(config, "data-dir", m_data->m_datadir.c_str()); + args.push_back(string("--data-dir=") + m_data->m_datadir); + cmdstring += string(" ") + args.back(); #endif if (m_data->m_addCreateParam.size() > ldatadiroptsz) { - aapi.aspell_config_replace( - config, "local-data-dir", - m_data->m_addCreateParam.substr(ldatadiroptsz).c_str()); + args.push_back( + string("--local-data-dir=") + m_data->m_addCreateParam.substr(ldatadiroptsz)); + cmdstring += string(" ") + args.back(); } - // aapi.aspell_config_replace(config, "sug-edit-dist", "2"); - ret = aapi.new_aspell_speller(config); - aapi.delete_aspell_config(config); - if (aapi.aspell_error(ret) != 0) { - reason = aapi.aspell_error_message(ret); - aapi.delete_aspell_can_have_error(ret); + if (!m_data->m_addCreateParam.empty()) { + args.push_back(m_data->m_addCreateParam); + cmdstring += string(" ") + args.back(); + } + + args.push_back(string("--master=") + dicPath()); + cmdstring += string(" ") + args.back(); + + args.push_back(string("--sug-mode=fast")); + cmdstring += string(" ") + args.back(); + + args.push_back("pipe"); + cmdstring += string(" ") + args.back(); + + // Keep stderr by default when querying? + bool keepStderr = true; + m_config->getConfParam("aspellKeepStderr", &keepStderr); + if (!keepStderr) + m_data->m_speller.setStderr("/dev/null"); + + LOGDEB("Starting aspell command [" << cmdstring << "]\n"); + if (m_data->m_speller.startExec(m_data->m_exec, args, true, true) != 0) { + LOGERR("Can't start aspell\n"); return false; } - m_data->m_speller = aapi.to_aspell_speller(ret); + // Read initial line from aspell: version etc. + string line; + if (m_data->m_speller.getline(line, 2) <= 0) { + LOGERR("rclaspell: failed reading initial aspell line. Command was " << cmdstring << "\n"); + m_data->m_speller.zapChild(); + return false; + } + LOGDEB("rclaspell: aspell initial answer: [" << line << "]\n"); return true; } -bool Aspell::check(const string &iterm, string& reason) -{ - LOGDEB("Aspell::check [" << iterm << "]\n"); - string mterm(iterm); - - if (!Rcl::Db::isSpellingCandidate(mterm)) { - LOGDEB0("Aspell::check: [" << mterm << - " not spelling candidate, return true\n"); - return true; - } - if (!ok() || !make_speller(reason)) - return false; - if (iterm.empty()) - return true; //?? - - if (!o_index_stripchars) { - string lower; - if (!unacmaybefold(mterm, lower, "UTF-8", UNACOP_FOLD)) { - LOGERR("Aspell::check: cant lowercase input\n"); - return false; - } - mterm.swap(lower); - } - - int ret = aapi.aspell_speller_check(m_data->m_speller, - mterm.c_str(), mterm.length()); - reason.clear(); - switch (ret) { - case 0: return false; - case 1: return true; - default: - case -1: - reason.append("Aspell error: "); - reason.append(aapi.aspell_speller_error_message(m_data->m_speller)); - return false; - } -} - -bool Aspell::suggest(Rcl::Db &db, const string &_term, - list& suggestions, string& reason) +bool Aspell::suggest( + Rcl::Db &db, const string &_term, vector& suggestions, string& reason) { LOGDEB("Aspell::suggest: term [" << _term << "]\n"); if (!ok() || !make_speller(reason)) @@ -496,8 +329,7 @@ bool Aspell::suggest(Rcl::Db &db, const string &_term, return true; //?? if (!Rcl::Db::isSpellingCandidate(mterm)) { - LOGDEB0("Aspell::suggest: [" << mterm << - " not spelling candidate, return empty/true\n"); + LOGDEB0("Aspell::suggest: [" << mterm << " not spelling candidate, return empty/true\n"); return true; } @@ -510,27 +342,37 @@ bool Aspell::suggest(Rcl::Db &db, const string &_term, mterm.swap(lower); } - const AspellWordList *wl = - aapi.aspell_speller_suggest(m_data->m_speller, - mterm.c_str(), mterm.length()); - if (wl == 0) { - reason = aapi.aspell_speller_error_message(m_data->m_speller); + m_data->m_speller.send(mterm + "\n"); + std::string line; + if (m_data->m_speller.getline(line, 3) <= 0) { + reason.append("Aspell error: "); return false; } - AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl); - const char *word; - while ((word = aapi.aspell_string_enumeration_next(els)) != 0) { - LOGDEB0("Aspell::suggest: got [" << word << "]\n"); - // Check that the word exists in the index (we don't want - // aspell computed stuff, only exact terms from the - // dictionary). We used to also check that it stems - // differently from the base word but this is complicated - // (stemming on/off + language), so we now leave this to the - // caller. + LOGDEB1("ASPELL: got answer: " << line << "\n"); + string empty; + if (m_data->m_speller.getline(empty, 1) <= 0) { + reason.append("Aspell: failed reading final empty line\n"); + return false; + } + + if (line[0] == '*' || line[0] == '#') { + // Word is in dictionary, or there are no suggestions + return true; + } + string::size_type colon; + // Aspell suggestions line: & original count offset: miss, miss, … + if (line[0] != '&' || (colon = line.find(':')) == string::npos || colon == line.size()-1) { + // ?? + reason.append("Aspell: bad answer line: "); + reason.append(line); + return false; + } + std::vector words; + stringSplitString(line.substr(colon + 2), words, ", "); + for (const auto& word : words) { if (db.termExists(word)) suggestions.push_back(word); } - aapi.delete_aspell_string_enumeration(els); return true; } diff --git a/src/aspell/rclaspell.h b/src/aspell/rclaspell.h index 609c240f..67126f7b 100644 --- a/src/aspell/rclaspell.h +++ b/src/aspell/rclaspell.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 J.F.Dockes +/* Copyright (C) 2006-2021 J.F.Dockes * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -27,12 +27,10 @@ * exist in the document set for a given word. * A specific aspell dictionary is created out of all the terms in the * xapian index, and we then use it to expand a term to spelling neighbours. - * We use the aspell C api for term expansion, but have - * to execute the program to create dictionaries. */ #include -#include +#include #include "rclconfig.h" #include "rcldb.h" @@ -40,7 +38,7 @@ class AspellData; class Aspell { - public: +public: Aspell(const RclConfig *cnf); ~Aspell(); @@ -54,19 +52,11 @@ class Aspell { * of an indexing pass. */ bool buildDict(Rcl::Db &db, std::string &reason); - /** Check that word is in dictionary. Note that this would mean - * that the EXACT word is: aspell just does a lookup, no - * grammatical, case or diacritics magic of any kind - * - * @return true if word in dic, false if not. reason.size() -> error - */ - bool check(const std::string& term, std::string& reason); - /** Return a list of possible expansions for a given word */ bool suggest(Rcl::Db &db, const std::string& term, - std::list &suggestions, std::string &reason); - - private: + std::vector &suggestions, std::string &reason); + +private: std::string dicPath(); const RclConfig *m_config; std::string m_lang; diff --git a/src/common/autoconfig-mac.h b/src/common/autoconfig-mac.h index f0f1721f..a778243b 100644 --- a/src/common/autoconfig-mac.h +++ b/src/common/autoconfig-mac.h @@ -10,9 +10,6 @@ /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ -/* Path to the aspell api include file */ -#define ASPELL_INCLUDE "../aspell/aspell-local.h" - /* Path to the aspell program */ #define ASPELL_PROG "/opt/local/bin/aspell" diff --git a/src/common/autoconfig-win.h b/src/common/autoconfig-win.h index 4402a698..ec0178da 100644 --- a/src/common/autoconfig-win.h +++ b/src/common/autoconfig-win.h @@ -4,9 +4,6 @@ /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ -/* Path to the aspell api include file */ -#define ASPELL_INCLUDE "aspell-local.h" - /* Aspell program parameter to findFilter(). */ #define ASPELL_PROG "aspell-installed/mingw32/bin/aspell" diff --git a/src/common/autoconfig.h.in b/src/common/autoconfig.h.in index d77ab61b..3a8efc0e 100644 --- a/src/common/autoconfig.h.in +++ b/src/common/autoconfig.h.in @@ -3,9 +3,6 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD -/* Path to the aspell api include file */ -#undef ASPELL_INCLUDE - /* Path to the aspell program */ #undef ASPELL_PROG diff --git a/src/configure.ac b/src/configure.ac index 6dc84188..7eb6ebea 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -114,20 +114,8 @@ if test X$withAspell != Xno ; then if test X$aspellProg != X ; then aspellBase=`dirname $aspellProg` aspellBase=`dirname $aspellBase` - AC_DEFINE_UNQUOTED(ASPELL_PROG, "$aspellProg", - [Path to the aspell program]) - if test -f $aspellBase/include/aspell.h ; then - AC_DEFINE_UNQUOTED(ASPELL_INCLUDE, "$aspellBase/include/aspell.h", - [Path to the aspell api include file]) - else - AC_MSG_NOTICE([aspell support enabled but aspell package not found. Compiling with internal aspell interface file]) - AC_DEFINE(ASPELL_INCLUDE, ["aspell-local.h"]) - fi - else - # aspell support enabled but no aspell install yet - AC_MSG_NOTICE([aspell support enabled but aspell package not found. Compiling with internal aspell interface file]) - AC_DEFINE(ASPELL_INCLUDE, ["aspell-local.h"]) - fi + AC_DEFINE_UNQUOTED(ASPELL_PROG, "$aspellProg", [Path to the aspell program]) + fi fi if test -f /usr/include/sys/inotify.h -o -f /usr/include/linux/inotify.h; then diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index 084b8421..e367cb08 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -1453,14 +1453,11 @@ bool Db::getSpellingSuggestions(const string& word, vector& suggs) return false; } - list asuggs; string reason; - if (!m_aspell->suggest(*this, term, asuggs, reason)) { - LOGERR("Db::getSpellingSuggestions: aspell failed: " << reason << - "\n"); + if (!m_aspell->suggest(*this, term, suggs, reason)) { + LOGERR("Db::getSpellingSuggestions: aspell failed: " << reason << "\n"); return false; } - suggs = vector(asuggs.begin(), asuggs.end()); #endif } else { #ifdef TESTING_XAPIAN_SPELL diff --git a/src/testmains/traspell.cpp b/src/testmains/traspell.cpp index b1a6ace4..624867f9 100644 --- a/src/testmains/traspell.cpp +++ b/src/testmains/traspell.cpp @@ -37,11 +37,10 @@ static char *thisprog; RclConfig *rclconfig; static char usage [] = -" -b : build dictionary\n" -" -s : suggestions for term\n" -" -c : check term\n" -"\n" -; + " -b : build dictionary\n" + " -s : suggestions for term\n" + "\n" + ; static void Usage(void) { @@ -63,83 +62,71 @@ int main(int argc, char **argv) argc--; argv++; while (argc > 0 && **argv == '-') { - (*argv)++; - if (!(**argv)) - /* Cas du "adb - core" */ - Usage(); - while (**argv) - switch (*(*argv)++) { - case 'b': op_flags |= OPT_b; break; - case 'c': op_flags |= OPT_c; if (argc < 2) Usage(); - word = *(++argv); - argc--; - goto b1; - case 's': op_flags |= OPT_s; if (argc < 2) Usage(); - word = *(++argv); - argc--; - goto b1; - default: Usage(); break; - } + (*argv)++; + if (!(**argv)) + /* Cas du "adb - core" */ + Usage(); + while (**argv) + switch (*(*argv)++) { + case 'b': op_flags |= OPT_b; break; + case 'c': op_flags |= OPT_c; if (argc < 2) Usage(); + word = *(++argv); + argc--; + goto b1; + case 's': op_flags |= OPT_s; if (argc < 2) Usage(); + word = *(++argv); + argc--; + goto b1; + default: Usage(); break; + } b1: argc--; argv++; } if (argc != 0 || op_flags == 0) - Usage(); + Usage(); string reason; rclconfig = recollinit(0, 0, 0, reason); if (!rclconfig || !rclconfig->ok()) { - fprintf(stderr, "Configuration problem: %s\n", reason.c_str()); - exit(1); + fprintf(stderr, "Configuration problem: %s\n", reason.c_str()); + exit(1); } string dbdir = rclconfig->getDbDir(); if (dbdir.empty()) { - fprintf(stderr, "No db directory in configuration"); - exit(1); + fprintf(stderr, "No db directory in configuration"); + exit(1); } Rcl::Db rcldb(rclconfig); if (!rcldb.open(Rcl::Db::DbRO, 0)) { - fprintf(stderr, "Could not open database in %s\n", dbdir.c_str()); - exit(1); + fprintf(stderr, "Could not open database in %s\n", dbdir.c_str()); + exit(1); } Aspell aspell(rclconfig); if (!aspell.init(reason)) { - cerr << "Init failed: " << reason << endl; - exit(1); + cerr << "Init failed: " << reason << endl; + exit(1); } if (op_flags & OPT_b) { - if (!aspell.buildDict(rcldb, reason)) { - cerr << "buildDict failed: " << reason << endl; - exit(1); - } - } else if (op_flags & OPT_c) { - bool ret = aspell.check(word, reason); - if (!ret && reason.size()) { - cerr << "Aspell error: " << reason << endl; - return 1; - } - cout << word; - if (ret) { - cout << " is in dictionary" << endl; + if (!aspell.buildDict(rcldb, reason)) { + cerr << "buildDict failed: " << reason << endl; + exit(1); + } } else { - cout << " not in dictionary" << endl; - } - } else { - list suggs; - if (!aspell.suggest(rcldb, word, suggs, reason)) { - cerr << "suggest failed: " << reason << endl; - exit(1); - } - cout << "Suggestions for " << word << ":" << endl; - for (list::iterator it = suggs.begin(); - it != suggs.end(); it++) { - cout << *it << endl; - } + list suggs; + if (!aspell.suggest(rcldb, word, suggs, reason)) { + cerr << "suggest failed: " << reason << endl; + exit(1); + } + cout << "Suggestions for " << word << ":" << endl; + for (list::iterator it = suggs.begin(); + it != suggs.end(); it++) { + cout << *it << endl; + } } exit(0); }