sq_hunspell.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #if defined(SQ_USE_HUNSPELL) || defined(SQ_USE_HUNSPELL_STATIC)
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "squirrel.h"
  6. #include "sqstdblobimpl.h"
  7. #include "hunspell.h"
  8. ////////
  9. #include "dynamic_library.h"
  10. /*SquiLu
  11. local library_functions = [
  12. ["Hunhandle*", "Hunspell_create_key", "const char* affpath, const char* dpath, const char* key"],
  13. ["void", "Hunspell_destroy", "Hunhandle* pHunspell"],
  14. ["int", "Hunspell_add_dic", "Hunhandle* pHunspell, const char* dpath"],
  15. ["int", "Hunspell_spell", "Hunhandle* pHunspell, const char*"],
  16. ["char *", "Hunspell_get_dic_encoding", "Hunhandle* pHunspell"],
  17. ["int", "Hunspell_suggest", "Hunhandle* pHunspell, char*** slst, const char* word"],
  18. ["int", "Hunspell_analyze", "Hunhandle* pHunspell, char*** slst, const char* word"],
  19. ["int", "Hunspell_stem", "Hunhandle* pHunspell, char*** slst, const char* word"],
  20. ["int", "Hunspell_generate", "Hunhandle* pHunspell, char*** slst, const char* word, const char* word2"],
  21. ["int", "Hunspell_generate2", "Hunhandle* pHunspell, char*** slst, const char* word, char** desc, int n"],
  22. ["int", "Hunspell_add", "Hunhandle* pHunspell, const char* word"],
  23. ["int", "Hunspell_add_with_affix", "Hunhandle* pHunspell, const char* word, const char* example"],
  24. ["int", "Hunspell_remove", "Hunhandle* pHunspell, const char* word"],
  25. //next entry should be the last one
  26. //to make valid the test made on load_library function
  27. ["void", "Hunspell_free_list", "Hunhandle* pHunspell, char*** slst, int n"],
  28. ];
  29. function write_library_functions_declaration(){
  30. foreach(k,v in library_functions) {
  31. putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");");
  32. putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;");
  33. }
  34. }
  35. function write_library_functions_load(){
  36. foreach(k,v in library_functions){
  37. putsnl("dl" + v[1] + " = (" + v[1] + "_t) libdyn.dlsym(\"" + v[1] + "\");");
  38. putsnl("if(!dl" + v[1] + ") return false;");
  39. }
  40. }
  41. function write_library_functions_static_defines(){
  42. foreach(k,v in library_functions){
  43. putsnl("#define dl" + v[1] + " " + v[1]);
  44. }
  45. }
  46. SquiLu*/
  47. #ifdef SQ_USE_HUNSPELL_STATIC
  48. #define load_library(x) true
  49. //@write_library_functions_static_defines()
  50. // generated-code:begin
  51. #define dlHunspell_create_key Hunspell_create_key
  52. #define dlHunspell_destroy Hunspell_destroy
  53. #define dlHunspell_add_dic Hunspell_add_dic
  54. #define dlHunspell_spell Hunspell_spell
  55. #define dlHunspell_get_dic_encoding Hunspell_get_dic_encoding
  56. #define dlHunspell_suggest Hunspell_suggest
  57. #define dlHunspell_analyze Hunspell_analyze
  58. #define dlHunspell_stem Hunspell_stem
  59. #define dlHunspell_generate Hunspell_generate
  60. #define dlHunspell_generate2 Hunspell_generate2
  61. #define dlHunspell_add Hunspell_add
  62. #define dlHunspell_add_with_affix Hunspell_add_with_affix
  63. #define dlHunspell_remove Hunspell_remove
  64. #define dlHunspell_free_list Hunspell_free_list
  65. // generated-code:end
  66. #else
  67. static DynamicLibrary libdyn;
  68. //@write_library_functions_declaration();
  69. // generated-code:begin
  70. typedef Hunhandle* (*Hunspell_create_key_t)(const char* affpath, const char* dpath, const char* key);
  71. static Hunspell_create_key_t dlHunspell_create_key = 0;
  72. typedef void (*Hunspell_destroy_t)(Hunhandle* pHunspell);
  73. static Hunspell_destroy_t dlHunspell_destroy = 0;
  74. typedef int (*Hunspell_add_dic_t)(Hunhandle* pHunspell, const char* dpath);
  75. static Hunspell_add_dic_t dlHunspell_add_dic = 0;
  76. typedef int (*Hunspell_spell_t)(Hunhandle* pHunspell, const char*);
  77. static Hunspell_spell_t dlHunspell_spell = 0;
  78. typedef char * (*Hunspell_get_dic_encoding_t)(Hunhandle* pHunspell);
  79. static Hunspell_get_dic_encoding_t dlHunspell_get_dic_encoding = 0;
  80. typedef int (*Hunspell_suggest_t)(Hunhandle* pHunspell, char*** slst, const char* word);
  81. static Hunspell_suggest_t dlHunspell_suggest = 0;
  82. typedef int (*Hunspell_analyze_t)(Hunhandle* pHunspell, char*** slst, const char* word);
  83. static Hunspell_analyze_t dlHunspell_analyze = 0;
  84. typedef int (*Hunspell_stem_t)(Hunhandle* pHunspell, char*** slst, const char* word);
  85. static Hunspell_stem_t dlHunspell_stem = 0;
  86. typedef int (*Hunspell_generate_t)(Hunhandle* pHunspell, char*** slst, const char* word, const char* word2);
  87. static Hunspell_generate_t dlHunspell_generate = 0;
  88. typedef int (*Hunspell_generate2_t)(Hunhandle* pHunspell, char*** slst, const char* word, char** desc, int n);
  89. static Hunspell_generate2_t dlHunspell_generate2 = 0;
  90. typedef int (*Hunspell_add_t)(Hunhandle* pHunspell, const char* word);
  91. static Hunspell_add_t dlHunspell_add = 0;
  92. typedef int (*Hunspell_add_with_affix_t)(Hunhandle* pHunspell, const char* word, const char* example);
  93. static Hunspell_add_with_affix_t dlHunspell_add_with_affix = 0;
  94. typedef int (*Hunspell_remove_t)(Hunhandle* pHunspell, const char* word);
  95. static Hunspell_remove_t dlHunspell_remove = 0;
  96. typedef void (*Hunspell_free_list_t)(Hunhandle* pHunspell, char*** slst, int n);
  97. static Hunspell_free_list_t dlHunspell_free_list = 0;
  98. // generated-code:end
  99. static const char *dynamicLibName = DYNLIB_FOR_OS(libhunspell-1.6);
  100. static bool load_library(const char *libname)
  101. {
  102. if(dlHunspell_free_list) return true;
  103. if(libdyn.open(libname))
  104. {
  105. //@write_library_functions_load();
  106. // generated-code:begin
  107. dlHunspell_create_key = (Hunspell_create_key_t) libdyn.dlsym("Hunspell_create_key");
  108. if(!dlHunspell_create_key) return false;
  109. dlHunspell_destroy = (Hunspell_destroy_t) libdyn.dlsym("Hunspell_destroy");
  110. if(!dlHunspell_destroy) return false;
  111. dlHunspell_add_dic = (Hunspell_add_dic_t) libdyn.dlsym("Hunspell_add_dic");
  112. if(!dlHunspell_add_dic) return false;
  113. dlHunspell_spell = (Hunspell_spell_t) libdyn.dlsym("Hunspell_spell");
  114. if(!dlHunspell_spell) return false;
  115. dlHunspell_get_dic_encoding = (Hunspell_get_dic_encoding_t) libdyn.dlsym("Hunspell_get_dic_encoding");
  116. if(!dlHunspell_get_dic_encoding) return false;
  117. dlHunspell_suggest = (Hunspell_suggest_t) libdyn.dlsym("Hunspell_suggest");
  118. if(!dlHunspell_suggest) return false;
  119. dlHunspell_analyze = (Hunspell_analyze_t) libdyn.dlsym("Hunspell_analyze");
  120. if(!dlHunspell_analyze) return false;
  121. dlHunspell_stem = (Hunspell_stem_t) libdyn.dlsym("Hunspell_stem");
  122. if(!dlHunspell_stem) return false;
  123. dlHunspell_generate = (Hunspell_generate_t) libdyn.dlsym("Hunspell_generate");
  124. if(!dlHunspell_generate) return false;
  125. dlHunspell_generate2 = (Hunspell_generate2_t) libdyn.dlsym("Hunspell_generate2");
  126. if(!dlHunspell_generate2) return false;
  127. dlHunspell_add = (Hunspell_add_t) libdyn.dlsym("Hunspell_add");
  128. if(!dlHunspell_add) return false;
  129. dlHunspell_add_with_affix = (Hunspell_add_with_affix_t) libdyn.dlsym("Hunspell_add_with_affix");
  130. if(!dlHunspell_add_with_affix) return false;
  131. dlHunspell_remove = (Hunspell_remove_t) libdyn.dlsym("Hunspell_remove");
  132. if(!dlHunspell_remove) return false;
  133. dlHunspell_free_list = (Hunspell_free_list_t) libdyn.dlsym("Hunspell_free_list");
  134. if(!dlHunspell_free_list) return false;
  135. // generated-code:end
  136. return true;
  137. }
  138. return false;
  139. }
  140. #endif // SQ_USE_HUNSPELL_STATIC
  141. SQ_OPT_STRING_STRLEN();
  142. static const SQChar HUNSPELL_Tag[] = _SC("sqhunspell");
  143. #define GET_hunspell_INSTANCE() SQ_GET_INSTANCE(v, 1, Hunhandle, HUNSPELL_Tag) \
  144. if(self == NULL) return sq_throwerror(v, _SC("sqhunspell object already closed"));
  145. static SQRESULT sq_hunspell_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  146. {
  147. Hunhandle *self = ((Hunhandle *)p);
  148. if(self)
  149. {
  150. dlHunspell_destroy(self);
  151. }
  152. return 1;
  153. }
  154. static SQRESULT sq_hunspell_constructor(HSQUIRRELVM v)
  155. {
  156. if(!load_library(dynamicLibName)) return sq_throwerror(v, _SC("Failed to load libhunspell !"));
  157. SQ_FUNC_VARS(v);
  158. SQ_GET_STRING(v, 2, aff);
  159. SQ_GET_STRING(v, 3, dic);
  160. SQ_OPT_STRING(v, 4, key, NULL);
  161. Hunhandle *self = dlHunspell_create_key(aff, dic, key);
  162. sq_setinstanceup(v,1,self);
  163. sq_setreleasehook(v,1,sq_hunspell_releasehook);
  164. return 0;
  165. }
  166. static SQRESULT sq_hunspell_add_dic(HSQUIRRELVM v)
  167. {
  168. SQ_FUNC_VARS_NO_TOP(v);
  169. GET_hunspell_INSTANCE();
  170. SQ_GET_STRING(v, 2, dpath);
  171. sq_pushinteger(v, dlHunspell_add_dic(self, dpath));
  172. return 1;
  173. }
  174. static SQRESULT sq_hunspell_list(HSQUIRRELVM v, Hunhandle* pHunspell, int nelms, char **list)
  175. {
  176. sq_newarray(v, nelms);
  177. for (int i = 0; i < nelms; i++)
  178. {
  179. sq_pushstring(v, list[i], -1);
  180. sq_arrayset(v, -2, i);
  181. }
  182. dlHunspell_free_list(pHunspell, &list, nelms);
  183. return 1;
  184. }
  185. static SQRESULT sq_hunspell_analyze(HSQUIRRELVM v)
  186. {
  187. SQ_FUNC_VARS_NO_TOP(v);
  188. GET_hunspell_INSTANCE();
  189. SQ_GET_STRING(v, 2, word);
  190. char **list = NULL;
  191. int nelms = dlHunspell_analyze(self, &list, word);
  192. return sq_hunspell_list(v, self, nelms, list);
  193. }
  194. static SQRESULT sq_hunspell_generate(HSQUIRRELVM v)
  195. {
  196. SQ_FUNC_VARS_NO_TOP(v);
  197. GET_hunspell_INSTANCE();
  198. SQ_GET_STRING(v, 2, word);
  199. char **list;
  200. const SQChar *str;
  201. int nelms;
  202. switch(sq_gettype(v, 3))
  203. {
  204. case OT_STRING:
  205. {
  206. SQ_GET_STRING(v, 3, example);
  207. nelms = dlHunspell_generate(self, &list, word, example);
  208. return sq_hunspell_list(v, self, nelms, list);
  209. }
  210. break;
  211. case OT_ARRAY:
  212. {
  213. int howmany = sq_getsize(v, 3);
  214. char **desc = (char**)sq_getscratchpad(v, howmany);
  215. for (int i=0; i<howmany; i++) {
  216. sq_arrayget(v, 3, i);
  217. if(sq_gettype(v, -1) != OT_STRING) return sq_throwerror(v, _SC("only strings are allowed in the supplied array"));
  218. sq_getstring(v, -1, &str);
  219. desc[i] = (char*)str; // nasty
  220. sq_poptop(v);
  221. }
  222. nelms = dlHunspell_generate2(self, &list, word, desc, howmany);
  223. return sq_hunspell_list(v, self, nelms, list);
  224. }
  225. break;
  226. default:
  227. return sq_throwerror(v, _SC("string or array expected"));
  228. }
  229. return 0;
  230. }
  231. static SQRESULT sq_hunspell_spell(HSQUIRRELVM v)
  232. {
  233. SQ_FUNC_VARS_NO_TOP(v);
  234. GET_hunspell_INSTANCE();
  235. SQ_GET_STRING(v, 2, word);
  236. int ret = dlHunspell_spell(self, word);
  237. sq_pushbool(v, ret);
  238. return 1;
  239. }
  240. static SQRESULT sq_hunspell_stem(HSQUIRRELVM v)
  241. {
  242. SQ_FUNC_VARS_NO_TOP(v);
  243. GET_hunspell_INSTANCE();
  244. SQ_GET_STRING(v, 2, word);
  245. char **list;
  246. int nelms = dlHunspell_stem(self, &list, word);
  247. return sq_hunspell_list(v, self, nelms, list);
  248. }
  249. static SQRESULT sq_hunspell_suggest(HSQUIRRELVM v)
  250. {
  251. SQ_FUNC_VARS(v);
  252. GET_hunspell_INSTANCE();
  253. SQ_GET_STRING(v, 2, word);
  254. SQ_OPT_INTEGER(v, 3, max_suggestion, 0);
  255. char **list;
  256. int nelms = dlHunspell_suggest(self, &list, word);
  257. if(max_suggestion)
  258. {
  259. if(max_suggestion == 1)
  260. {
  261. if(nelms)
  262. {
  263. sq_pushstring(v, list[0], -1);
  264. dlHunspell_free_list(self, &list, nelms);
  265. }
  266. else sq_pushnull(v);
  267. return 1;
  268. }
  269. if(nelms > max_suggestion) nelms = max_suggestion;
  270. }
  271. return sq_hunspell_list(v, self, nelms, list);
  272. }
  273. static SQRESULT sq_hunspell_add_word(HSQUIRRELVM v)
  274. {
  275. SQ_FUNC_VARS_NO_TOP(v);
  276. GET_hunspell_INSTANCE();
  277. SQ_GET_STRING(v, 2, word);
  278. sq_pushinteger(v, dlHunspell_add(self, word));
  279. return 1;
  280. }
  281. static SQRESULT sq_hunspell_remove_word(HSQUIRRELVM v)
  282. {
  283. SQ_FUNC_VARS_NO_TOP(v);
  284. GET_hunspell_INSTANCE();
  285. SQ_GET_STRING(v, 2, word);
  286. sq_pushinteger(v, dlHunspell_remove(self, word));
  287. return 1;
  288. }
  289. static SQRESULT sq_hunspell_get_dic_encoding(HSQUIRRELVM v)
  290. {
  291. SQ_FUNC_VARS_NO_TOP(v);
  292. GET_hunspell_INSTANCE();
  293. char* encoding = dlHunspell_get_dic_encoding(self);
  294. sq_pushstring(v, encoding, -1);
  295. return 1;
  296. }
  297. static SQRESULT sq_hunspell__typeof(HSQUIRRELVM v)
  298. {
  299. sq_pushstring(v,_SC(HUNSPELL_Tag),-1);
  300. return 1;
  301. }
  302. static SQRESULT sq_hunspell_loadlib(HSQUIRRELVM v)
  303. {
  304. SQ_FUNC_VARS_NO_TOP(v);
  305. SQ_GET_STRING(v, 2, libname);
  306. sq_pushbool(v, load_library(libname));
  307. return 1;
  308. }
  309. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_hunspell_##name,nparams,tycheck}
  310. static SQRegFunction sq_hunspell_methods[] =
  311. {
  312. _DECL_FUNC(constructor,-3,_SC(".sss")),
  313. _DECL_FUNC(add_dic,2,_SC("xs")),
  314. _DECL_FUNC(analyze,2,_SC("xs")),
  315. _DECL_FUNC(generate,-2,_SC("x s|a")),
  316. _DECL_FUNC(spell,2,_SC("xs")),
  317. _DECL_FUNC(stem,2,_SC("xs")),
  318. _DECL_FUNC(suggest,-2,_SC("xsi")),
  319. _DECL_FUNC(add_word,2,_SC("xs")),
  320. _DECL_FUNC(remove_word,2,_SC("xs")),
  321. _DECL_FUNC(get_dic_encoding,1,_SC("x")),
  322. _DECL_FUNC(_typeof,1,_SC("x")),
  323. _DECL_FUNC(loadlib,2,_SC(".s")),
  324. {0,0}
  325. };
  326. #undef _DECL_FUNC
  327. #ifdef __cplusplus
  328. extern "C" {
  329. #endif
  330. SQRESULT sqext_register_hunspell(HSQUIRRELVM v)
  331. {
  332. sq_pushstring(v,HUNSPELL_Tag,-1);
  333. sq_newclass(v,SQFalse);
  334. sq_settypetag(v,-1,(void*)HUNSPELL_Tag);
  335. sq_insert_reg_funcs(v, sq_hunspell_methods);
  336. sq_newslot(v,-3,SQTrue);
  337. return 0;
  338. }
  339. #ifdef __cplusplus
  340. }
  341. #endif
  342. #endif //SQ_USE_HUNSPELL