sq_tre.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. #if defined(SQ_USE_TRE) || defined(SQ_USE_TRE_STATIC)
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "squirrel.h"
  6. #include "sqstdblobimpl.h"
  7. #include "tre/tre.h"
  8. ////////
  9. #include "dynamic_library.h"
  10. /*SquiLu
  11. local library_functions = [
  12. ["int", "tre_regncomp", "regex_t *preg, const char *regex, size_t len, int cflags"],
  13. //["int", "tre_regwncomp", "regex_t *preg, const wchar_t *regex, size_t len, int cflags"],
  14. ["int", "tre_regnexec", "const regex_t *preg, const char *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags"],
  15. ["int", "tre_reganexec", "const regex_t *preg, const char *string, size_t len, regamatch_t *match, regaparams_t params, int eflags"],
  16. //["int", "tre_regwnexec", "const regex_t *preg, const wchar_t *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags"],
  17. //["int", "tre_regawnexec", "const regex_t *preg, const wchar_t *string, size_t len, regamatch_t *match, regaparams_t params, int eflags"],
  18. ["void", "tre_regaparams_default", "regaparams_t *params"],
  19. ["int", "tre_config", "int query, void *result"],
  20. ["int", "tre_have_backrefs", "const regex_t *preg"],
  21. ["int", "tre_have_approx", "const regex_t *preg"],
  22. //["int", "tre_reguexec", "const regex_t *preg, const tre_str_source *string, size_t nmatch, regmatch_t pmatch[], int eflags"],
  23. ["size_t", "tre_regerror", "int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size"],
  24. ["void", "tre_regfree", "regex_t *preg"],
  25. //next entry should be the last one
  26. //to make valid the test made on load_library function
  27. ["char *", "tre_version", "void"],
  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_TRE_STATIC
  48. #define load_library(x) true
  49. //@write_library_functions_static_defines()
  50. // generated-code:begin
  51. #define dltre_regncomp tre_regncomp
  52. #define dltre_regnexec tre_regnexec
  53. #define dltre_reganexec tre_reganexec
  54. #define dltre_regaparams_default tre_regaparams_default
  55. #define dltre_config tre_config
  56. #define dltre_have_backrefs tre_have_backrefs
  57. #define dltre_have_approx tre_have_approx
  58. #define dltre_regerror tre_regerror
  59. #define dltre_regfree tre_regfree
  60. #define dltre_version tre_version
  61. // generated-code:end
  62. #else
  63. static DynamicLibrary libdyn;
  64. //@write_library_functions_declaration();
  65. // generated-code:begin
  66. typedef int (*tre_regncomp_t)(regex_t *preg, const char *regex, size_t len, int cflags);
  67. static tre_regncomp_t dltre_regncomp = 0;
  68. typedef int (*tre_regnexec_t)(const regex_t *preg, const char *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags);
  69. static tre_regnexec_t dltre_regnexec = 0;
  70. typedef int (*tre_reganexec_t)(const regex_t *preg, const char *string, size_t len, regamatch_t *match, regaparams_t params, int eflags);
  71. static tre_reganexec_t dltre_reganexec = 0;
  72. typedef void (*tre_regaparams_default_t)(regaparams_t *params);
  73. static tre_regaparams_default_t dltre_regaparams_default = 0;
  74. typedef int (*tre_config_t)(int query, void *result);
  75. static tre_config_t dltre_config = 0;
  76. typedef int (*tre_have_backrefs_t)(const regex_t *preg);
  77. static tre_have_backrefs_t dltre_have_backrefs = 0;
  78. typedef int (*tre_have_approx_t)(const regex_t *preg);
  79. static tre_have_approx_t dltre_have_approx = 0;
  80. typedef size_t (*tre_regerror_t)(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
  81. static tre_regerror_t dltre_regerror = 0;
  82. typedef void (*tre_regfree_t)(regex_t *preg);
  83. static tre_regfree_t dltre_regfree = 0;
  84. typedef char * (*tre_version_t)(void);
  85. static tre_version_t dltre_version = 0;
  86. // generated-code:end
  87. static const char *dynamicLibName = DYNLIB_FOR_OS(libtre);
  88. static bool load_library(const char *libname)
  89. {
  90. if(dltre_version) return true;
  91. if(libdyn.open(libname))
  92. {
  93. //@write_library_functions_load();
  94. // generated-code:begin
  95. dltre_regncomp = (tre_regncomp_t) libdyn.dlsym("tre_regncomp");
  96. if(!dltre_regncomp) return false;
  97. dltre_regnexec = (tre_regnexec_t) libdyn.dlsym("tre_regnexec");
  98. if(!dltre_regnexec) return false;
  99. dltre_reganexec = (tre_reganexec_t) libdyn.dlsym("tre_reganexec");
  100. if(!dltre_reganexec) return false;
  101. dltre_regaparams_default = (tre_regaparams_default_t) libdyn.dlsym("tre_regaparams_default");
  102. if(!dltre_regaparams_default) return false;
  103. dltre_config = (tre_config_t) libdyn.dlsym("tre_config");
  104. if(!dltre_config) return false;
  105. dltre_have_backrefs = (tre_have_backrefs_t) libdyn.dlsym("tre_have_backrefs");
  106. if(!dltre_have_backrefs) return false;
  107. dltre_have_approx = (tre_have_approx_t) libdyn.dlsym("tre_have_approx");
  108. if(!dltre_have_approx) return false;
  109. dltre_regerror = (tre_regerror_t) libdyn.dlsym("tre_regerror");
  110. if(!dltre_regerror) return false;
  111. dltre_regfree = (tre_regfree_t) libdyn.dlsym("tre_regfree");
  112. if(!dltre_regfree) return false;
  113. dltre_version = (tre_version_t) libdyn.dlsym("tre_version");
  114. if(!dltre_version) return false;
  115. // generated-code:end
  116. return true;
  117. }
  118. return false;
  119. }
  120. #endif // SQ_USE_TRE_STATIC
  121. static SQInteger calc_new_size_by_max_len(SQInteger start_pos, SQInteger max_len, SQInteger curr_size)
  122. {
  123. SQInteger new_size;
  124. if(start_pos < 0)
  125. {
  126. new_size = curr_size + start_pos;
  127. start_pos = new_size < 0 ? 0 : new_size;
  128. }
  129. if(max_len > 0) new_size = start_pos + max_len;
  130. else new_size = curr_size + max_len;
  131. if( (new_size < curr_size) && (new_size > start_pos) )
  132. {
  133. return new_size;
  134. }
  135. return curr_size;
  136. }
  137. struct sqtre_st {
  138. regex_t re;
  139. regamatch_t amatch;
  140. regaparams_t aparams;
  141. /* associated squirrel vm */
  142. //HSQUIRRELVM v;
  143. };
  144. static const SQChar TRE_Tag[] = _SC("sqtre");
  145. #define GET_tre_INSTANCE() SQ_GET_INSTANCE(v, 1, sqtre_st, TRE_Tag) \
  146. if(self == NULL) return sq_throwerror(v, _SC("sqtre object already closed"));
  147. static SQRESULT generate_error (HSQUIRRELVM v, const sqtre_st *sqtre, int errcode) {
  148. char errbuf[80];
  149. tre_regerror (errcode, &sqtre->re, errbuf, sizeof (errbuf));
  150. return sq_throwerror(v, _SC("%s"), errbuf);
  151. }
  152. static SQRESULT sq_tre_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  153. {
  154. sqtre_st *self = ((sqtre_st *)p);
  155. if(self)
  156. {
  157. if(self->amatch.pmatch)
  158. {
  159. sq_free(self->amatch.pmatch, self->amatch.nmatch * sizeof(*self->amatch.pmatch));
  160. }
  161. dltre_regfree(&self->re);
  162. sq_free(self, sizeof(*self));
  163. }
  164. return 1;
  165. }
  166. static SQRESULT sq_tre_constructor(HSQUIRRELVM v)
  167. {
  168. if(!load_library(dynamicLibName)) return sq_throwerror(v, _SC("Failed to load libtre !"));
  169. SQ_FUNC_VARS(v);
  170. SQ_GET_STRING(v, 2, pattern);
  171. SQ_OPT_INTEGER(v, 3, eflags, REG_EXTENDED);
  172. sqtre_st *sqtre = (sqtre_st *)sq_malloc(sizeof(*sqtre));
  173. memset(sqtre, 0, sizeof(sqtre_st));
  174. //sqtre->v = v;
  175. int rc = dltre_regncomp(
  176. &sqtre->re,
  177. pattern, /* the pattern */
  178. pattern_size,
  179. eflags); /* 0 = default eflags */
  180. if(rc)
  181. {
  182. SQRESULT res = generate_error(v, sqtre, rc);
  183. sq_free(sqtre, sizeof(sqtre_st));
  184. return res;
  185. }
  186. if (eflags & REG_NOSUB) sqtre->re.re_nsub = 0;
  187. else
  188. {
  189. sqtre->amatch.nmatch = sqtre->re.re_nsub+1; //+1 fror the whole match at 0
  190. sqtre->amatch.pmatch = (regmatch_t *) sq_malloc(sqtre->amatch.nmatch * sizeof (regmatch_t));
  191. }
  192. /*
  193. sq_resetobject(&sqtre->callout_cb);
  194. sq_resetobject(&sqtre->callout_cb_udata);
  195. */
  196. sq_setinstanceup(v,1,sqtre);
  197. sq_setreleasehook(v,1,sq_tre_releasehook);
  198. return 0;
  199. }
  200. static SQRESULT sq_tre_exec(HSQUIRRELVM v)
  201. {
  202. SQ_FUNC_VARS(v);
  203. GET_tre_INSTANCE();
  204. SQ_GET_STRING(v, 2, subject);
  205. SQ_OPT_INTEGER(v, 4, start_offset, 0);
  206. SQ_OPT_INTEGER(v, 5, eflags, 0);
  207. SQ_OPT_INTEGER(v, 6, max_len, 0);
  208. if(max_len)
  209. {
  210. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  211. }
  212. int rc = dltre_reganexec(
  213. &self->re, /* the compiled pattern */
  214. subject+start_offset, /* the subject string */
  215. subject_size, /* the length of the subject */
  216. &self->amatch,
  217. self->aparams,
  218. eflags); /* 0 = default eflags */
  219. const int array_pos = 3;
  220. SQInteger rtype = sq_gettype(v, array_pos);
  221. if (rc == 0)
  222. {
  223. if(rtype == OT_ARRAY)
  224. {
  225. int nelms = self->amatch.nmatch;
  226. regmatch_t *pmatch = self->amatch.pmatch;
  227. sq_clear(v, array_pos);
  228. for (int i = 0; i < nelms; i++)
  229. {
  230. SQInteger pos = pmatch[i].rm_so;
  231. sq_pushinteger(v, pos);
  232. sq_arrayappend(v, array_pos);
  233. pos = pmatch[i].rm_eo;
  234. sq_pushinteger(v, pos);
  235. sq_arrayappend(v, array_pos);
  236. }
  237. }
  238. }
  239. sq_pushinteger(v, rc);
  240. return 1;
  241. }
  242. static SQRESULT sq_tre_match(HSQUIRRELVM v)
  243. {
  244. SQ_FUNC_VARS(v);
  245. GET_tre_INSTANCE();
  246. SQ_GET_STRING(v, 2, subject);
  247. SQ_OPT_INTEGER(v, 3, start_offset, 0);
  248. SQ_OPT_INTEGER(v, 4, eflags, 0);
  249. SQ_OPT_INTEGER(v, 5, max_len, 0);
  250. if(max_len)
  251. {
  252. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  253. }
  254. int rc = dltre_reganexec(
  255. &self->re, /* the compiled pattern */
  256. subject+start_offset, /* the subject string */
  257. subject_size, /* the length of the subject */
  258. &self->amatch,
  259. self->aparams,
  260. eflags); /* 0 = default eflags */
  261. if(rc == 0)
  262. {
  263. regmatch_t *pmatch = self->amatch.pmatch;
  264. SQInteger start_pos = pmatch[0].rm_so, end_pos = pmatch[0].rm_eo;
  265. if(start_pos == end_pos) sq_pushinteger(v, start_pos); //empty match return it's position
  266. else sq_pushstring(v, subject + start_pos, end_pos - start_pos);
  267. return 1;
  268. }
  269. if(rc == REG_ESPACE) //only no matching errore
  270. {
  271. return sq_throwerror(v, _SC("tre_match error %d"), (int)rc);
  272. }
  273. return 0;
  274. }
  275. static SQRESULT sq_tre_gmatch(HSQUIRRELVM v)
  276. {
  277. SQ_FUNC_VARS(v);
  278. GET_tre_INSTANCE();
  279. SQ_GET_STRING(v, 2, subject);
  280. SQ_OPT_INTEGER(v, 4, start_offset, 0);
  281. SQ_OPT_INTEGER(v, 5, eflags, 0);
  282. SQ_OPT_INTEGER(v, 6, max_len, 0);
  283. SQInteger rc;
  284. bool isFirst = true;
  285. if(max_len)
  286. {
  287. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  288. }
  289. regmatch_t *pmatch = self->amatch.pmatch;
  290. SQInteger nmatch = self->amatch.nmatch;
  291. while( (rc = dltre_reganexec(
  292. &self->re, /* the compiled pattern */
  293. subject+start_offset, /* the subject string */
  294. subject_size, /* the length of the subject */
  295. &self->amatch,
  296. self->aparams,
  297. eflags)) == 0) /* use default match context */
  298. {
  299. if(isFirst)
  300. {
  301. sq_push(v, 3); //push the function
  302. isFirst = false;
  303. }
  304. sq_pushroottable(v); //this
  305. SQInteger start_pos, end_pos, i = 0,
  306. param_count = 1; //root table already on the stack
  307. for(;i < nmatch; i++) {
  308. start_pos = pmatch[i].rm_so;
  309. end_pos = pmatch[i].rm_eo;
  310. if(start_pos == end_pos) sq_pushinteger(v, start_pos); //empty match return it's position
  311. else sq_pushstring(v, subject + start_offset + start_pos, end_pos - start_pos);
  312. ++param_count;
  313. }
  314. i = sq_call(v, param_count, SQTrue, SQTrue);
  315. if(i < 0) return i;
  316. SQObjectType rtype = sq_gettype(v, -1);
  317. SQBool keep_matching = SQFalse;
  318. if(rtype == OT_BOOL) {
  319. sq_getbool(v, -1, &keep_matching);
  320. }
  321. sq_poptop(v); //remove return parameter
  322. if(!keep_matching) break;
  323. start_offset += pmatch[nmatch-1].rm_eo; //the last match + 1
  324. }
  325. if(rc == REG_ESPACE) //only no matching errore
  326. {
  327. return sq_throwerror(v, _SC("tre_match error %d"), (int)rc);
  328. }
  329. return 0;
  330. }
  331. #include "sqstdblobimpl.h"
  332. static SQRESULT sq_tre_gsub(HSQUIRRELVM v)
  333. {
  334. SQ_FUNC_VARS(v);
  335. GET_tre_INSTANCE();
  336. SQ_GET_STRING(v, 2, subject);
  337. SQ_OPT_INTEGER(v, 4, start_offset, 0);
  338. SQ_OPT_INTEGER(v, 5, eflags, 0);
  339. SQ_OPT_INTEGER(v, 6, max_len, 0);
  340. if(max_len)
  341. {
  342. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  343. }
  344. SQBlob blob(0,8192);
  345. const int replacement_idx = 3;
  346. SQObjectType ptype = sq_gettype(v, replacement_idx);
  347. const SQChar *replacement;
  348. SQInteger replacement_size;
  349. SQInteger rc;
  350. bool isFirst = true;
  351. regmatch_t *pmatch = self->amatch.pmatch;
  352. SQInteger nmatch = self->amatch.nmatch;
  353. if(ptype == OT_STRING)
  354. {
  355. sq_getstr_and_size(v, replacement_idx, &replacement, &replacement_size);
  356. }
  357. while( (rc = dltre_reganexec(
  358. &self->re, /* the compiled pattern */
  359. subject+start_offset, /* the subject string */
  360. subject_size, /* the length of the subject */
  361. &self->amatch,
  362. self->aparams,
  363. eflags)) == 0) /* use default match context */
  364. {
  365. SQInteger i, start_pos, end_pos;
  366. blob.Write(subject+start_offset, pmatch[0].rm_so);
  367. switch(ptype){
  368. case OT_CLOSURE:{
  369. if(isFirst)
  370. {
  371. sq_push(v, replacement_idx); //push the function
  372. isFirst = false;
  373. }
  374. sq_pushroottable(v); //this
  375. SQInteger param_count = 1; //root table
  376. for(i=0; i < nmatch; i++) {
  377. start_pos = pmatch[i].rm_so;
  378. end_pos = pmatch[i].rm_eo;
  379. if(start_pos == end_pos) sq_pushinteger(v, start_pos);
  380. else sq_pushstring(v, subject + start_offset + start_pos, end_pos - start_pos);
  381. ++param_count;
  382. }
  383. i = sq_call(v, param_count, SQTrue, SQTrue);
  384. if(i < 0) return i;
  385. if(sq_gettype(v, -1) == OT_STRING){
  386. const SQChar *svalue;
  387. sq_getstring(v, -1, &svalue);
  388. blob.Write(svalue, sq_getsize(v, -1));
  389. }
  390. sq_poptop(v);
  391. }
  392. break;
  393. case OT_ARRAY:{
  394. SQInteger array_idx = 0;
  395. for(i=0; i < nmatch; i++) {
  396. sq_pushinteger(v, array_idx++);
  397. if(SQ_SUCCEEDED(sq_get(v, replacement_idx)) &&
  398. SQ_SUCCEEDED(sq_getstr_and_size(v, -1, &replacement, &replacement_size))){
  399. blob.Write(replacement, replacement_size);
  400. sq_pop(v, 1); //remove value
  401. }
  402. }
  403. }
  404. break;
  405. case OT_TABLE:{
  406. for(i=0; i < nmatch; i++) {
  407. start_pos = pmatch[i].rm_so;
  408. end_pos = pmatch[i].rm_eo;
  409. sq_pushstring(v, subject + start_offset + start_pos, end_pos - start_pos);
  410. if(SQ_SUCCEEDED(sq_get(v, replacement_idx)) &&
  411. SQ_SUCCEEDED(sq_getstr_and_size(v, -1, &replacement, &replacement_size))){
  412. blob.Write(replacement, replacement_size);
  413. sq_pop(v, 1); //remove value
  414. }
  415. }
  416. }
  417. break;
  418. case OT_STRING:{
  419. for(i=0; i < replacement_size; i++) {
  420. SQInteger c = replacement[i];
  421. switch(c)
  422. {
  423. case '$':
  424. ++i;
  425. if(i < replacement_size)
  426. {
  427. SQInteger idx = replacement[i] - '0', match_idx = 0;
  428. for(int j=0; j < nmatch; j++) {
  429. if(match_idx == idx)
  430. {
  431. start_pos = pmatch[j].rm_so;
  432. end_pos = pmatch[j].rm_eo;
  433. blob.Write(subject+start_offset+start_pos, end_pos-start_pos);
  434. break;
  435. }
  436. ++match_idx;
  437. }
  438. if(idx != match_idx)
  439. {
  440. return sq_throwerror(v, _SC("there is no match for replacement $%d"), idx);
  441. }
  442. continue;
  443. }
  444. else
  445. {
  446. return sq_throwerror(v, _SC("unexpected end of replacement string"));
  447. }
  448. break;
  449. case '\\':
  450. ++i;
  451. if(i < replacement_size)
  452. {
  453. blob.WriteChar(replacement[i]);
  454. continue;
  455. }
  456. //falthrough last character on replacement string
  457. default:
  458. blob.WriteChar(c);
  459. }
  460. }
  461. }
  462. break;
  463. default:
  464. return sq_throwerror(v, _SC("gsub only works with closure, array, table for replacement"));
  465. }
  466. start_offset += pmatch[nmatch-1].rm_eo; //the last match + 1
  467. }
  468. if(rc == REG_ESPACE) //only no matching errore
  469. {
  470. return sq_throwerror(v, _SC("tre_match error %d"), (int)rc);
  471. }
  472. if(subject_size) blob.Write(subject+start_offset, subject_size-start_offset);
  473. sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len());
  474. return 1;
  475. }
  476. static SQRESULT sq_tre_have_backrefs(HSQUIRRELVM v)
  477. {
  478. SQ_FUNC_VARS_NO_TOP(v);
  479. GET_tre_INSTANCE();
  480. sq_pushinteger(v, dltre_have_backrefs(&self->re));
  481. return 1;
  482. }
  483. static SQRESULT sq_tre_have_approx(HSQUIRRELVM v)
  484. {
  485. SQ_FUNC_VARS_NO_TOP(v);
  486. GET_tre_INSTANCE();
  487. sq_pushinteger(v, dltre_have_approx(&self->re));
  488. return 1;
  489. }
  490. static SQRESULT sq_tre__typeof(HSQUIRRELVM v)
  491. {
  492. sq_pushstring(v,_SC(TRE_Tag),-1);
  493. return 1;
  494. }
  495. static SQRESULT sq_tre_version(HSQUIRRELVM v)
  496. {
  497. const char *buf = dltre_version();
  498. sq_pushstring(v, (const SQChar*)buf, -1);
  499. return 1;
  500. }
  501. static SQRESULT sq_tre_loadlib(HSQUIRRELVM v)
  502. {
  503. SQ_FUNC_VARS_NO_TOP(v);
  504. SQ_GET_STRING(v, 2, libname);
  505. sq_pushbool(v, load_library(libname));
  506. return 1;
  507. }
  508. static SQRESULT sq_tre_regaparams_default(HSQUIRRELVM v)
  509. {
  510. SQ_FUNC_VARS_NO_TOP(v);
  511. GET_tre_INSTANCE();
  512. dltre_regaparams_default(&self->aparams);
  513. return 0;
  514. }
  515. static SQRESULT sq_tre_regamatch(HSQUIRRELVM v)
  516. {
  517. SQ_FUNC_VARS_NO_TOP(v);
  518. GET_tre_INSTANCE();
  519. SQ_GET_STRING(v, 2, pkey);
  520. #define GET_PKEY(skey) \
  521. else if(strcmp(pkey, #skey) == 0) \
  522. { \
  523. sq_pushinteger(v, self->amatch.skey); \
  524. }
  525. if(0){}
  526. GET_PKEY(cost)
  527. GET_PKEY(num_ins)
  528. GET_PKEY(num_del)
  529. GET_PKEY(num_subst)
  530. GET_PKEY(nmatch)
  531. else return sq_throwerror(v, _SC("unknown parameter '%s'"), pkey);
  532. return 1;
  533. }
  534. static SQRESULT sq_tre_regaparams(HSQUIRRELVM v)
  535. {
  536. SQ_FUNC_VARS(v);
  537. GET_tre_INSTANCE();
  538. SQ_GET_STRING(v, 2, pkey);
  539. SQ_OPT_INTEGER(v, 3, pvalue, 0);
  540. SQBool doSet = (_top_ == 3);
  541. #define GET_SET_PKEY(skey) \
  542. else if(strcmp(pkey, #skey) == 0) \
  543. { \
  544. sq_pushinteger(v, self->aparams.skey); \
  545. if(doSet) self->aparams.skey = pvalue; \
  546. }
  547. if(0){}
  548. GET_SET_PKEY(max_cost)
  549. GET_SET_PKEY(cost_ins)
  550. GET_SET_PKEY(cost_del)
  551. GET_SET_PKEY(cost_subst)
  552. GET_SET_PKEY(max_ins)
  553. GET_SET_PKEY(max_del)
  554. GET_SET_PKEY(max_subst)
  555. GET_SET_PKEY(max_err)
  556. else return sq_throwerror(v, _SC("unknown parameter '%s'"), pkey);
  557. return 1;
  558. }
  559. static SQRESULT sq_tre_config(HSQUIRRELVM v)
  560. {
  561. SQ_FUNC_VARS_NO_TOP(v);
  562. SQ_GET_INTEGER(v, 2, option);
  563. void *config_result;
  564. switch(option)
  565. {
  566. case TRE_CONFIG_APPROX:
  567. case TRE_CONFIG_WCHAR:
  568. case TRE_CONFIG_MULTIBYTE:
  569. case TRE_CONFIG_SYSTEM_ABI:
  570. tre_config(option, &config_result);
  571. sq_pushinteger(v, (SQInteger)config_result);
  572. break;
  573. case TRE_CONFIG_VERSION:
  574. tre_config(option, &config_result);
  575. sq_pushstring(v, (const SQChar*)config_result, -1);
  576. break;
  577. default:
  578. return sq_throwerror(v, _SC("unknown config option '%d'"), option);
  579. }
  580. return 1;
  581. }
  582. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_tre_##name,nparams,tycheck}
  583. static SQRegFunction sq_tre_methods[] =
  584. {
  585. _DECL_FUNC(constructor,-2,_SC(".sn")),
  586. _DECL_FUNC(config,2,_SC("xi")),
  587. _DECL_FUNC(regaparams_default,1,_SC("x")),
  588. _DECL_FUNC(regaparams,-2,_SC("xsi")),
  589. _DECL_FUNC(regamatch,2,_SC("xs")),
  590. _DECL_FUNC(exec,-3,_SC("xsannn")),
  591. _DECL_FUNC(match,-2,_SC("xsnnn")),
  592. _DECL_FUNC(gmatch,-3,_SC("xscnnn")),
  593. _DECL_FUNC(gsub,-3,_SC("xs s|c|a|t nnn")),
  594. _DECL_FUNC(_typeof,1,_SC("x")),
  595. _DECL_FUNC(version,1,_SC(".")),
  596. _DECL_FUNC(have_approx,1,_SC("x")),
  597. _DECL_FUNC(have_backrefs,1,_SC("x")),
  598. _DECL_FUNC(loadlib,2,_SC(".s")),
  599. {0,0}
  600. };
  601. #undef _DECL_FUNC
  602. typedef struct {
  603. const SQChar *Str;
  604. SQInteger Val;
  605. } KeyIntType, * KeyIntPtrType;
  606. static KeyIntType sqtre_constants[] = {
  607. #define MK_CONST(c) {_SC(#c), TRE_##c}
  608. #define MK_CONST2(c) {_SC(#c), (SQInteger)TRE_##c}
  609. #define MK_CONST_REG(c) {_SC(#c), (SQInteger)REG_##c}
  610. //MK_CONST(SSL_SESSION_ID_SIZE),
  611. MK_CONST2(CONFIG_VERSION),
  612. MK_CONST2(CONFIG_APPROX),
  613. MK_CONST2(CONFIG_WCHAR),
  614. MK_CONST2(CONFIG_MULTIBYTE),
  615. MK_CONST2(CONFIG_SYSTEM_ABI),
  616. MK_CONST_REG(OK),
  617. MK_CONST_REG(NOMATCH),
  618. MK_CONST_REG(BADPAT),
  619. MK_CONST_REG(ECOLLATE),
  620. MK_CONST_REG(ECTYPE),
  621. MK_CONST_REG(EESCAPE),
  622. MK_CONST_REG(ESUBREG),
  623. MK_CONST_REG(EBRACK),
  624. MK_CONST_REG(EPAREN),
  625. MK_CONST_REG(EBRACE),
  626. MK_CONST_REG(BADBR),
  627. MK_CONST_REG(ERANGE),
  628. MK_CONST_REG(ESPACE),
  629. MK_CONST_REG(BADRPT),
  630. MK_CONST_REG(EXTENDED),
  631. MK_CONST_REG(ICASE),
  632. MK_CONST_REG(NEWLINE),
  633. MK_CONST_REG(NOSUB),
  634. MK_CONST_REG(BASIC),
  635. MK_CONST_REG(LITERAL),
  636. MK_CONST_REG(RIGHT_ASSOC),
  637. MK_CONST_REG(UNGREEDY),
  638. MK_CONST_REG(NOTBOL),
  639. MK_CONST_REG(NOTEOL),
  640. MK_CONST_REG(APPROX_MATCHER),
  641. MK_CONST_REG(BACKTRACKING_MATCHER),
  642. {0,0}
  643. };
  644. #ifdef __cplusplus
  645. extern "C" {
  646. #endif
  647. SQRESULT sqext_register_tre(HSQUIRRELVM v)
  648. {
  649. sq_pushstring(v,TRE_Tag,-1);
  650. sq_newclass(v,SQFalse);
  651. sq_settypetag(v,-1,(void*)TRE_Tag);
  652. sq_insert_reg_funcs(v, sq_tre_methods);
  653. //add constants
  654. KeyIntPtrType KeyIntPtr;
  655. for (KeyIntPtr = sqtre_constants; KeyIntPtr->Str; KeyIntPtr++) {
  656. sq_pushstring(v, KeyIntPtr->Str, -1); //first the key
  657. sq_pushinteger(v, KeyIntPtr->Val); //then the value
  658. sq_newslot(v, -3, SQFalse); //store then
  659. }
  660. sq_newslot(v,-3,SQTrue);
  661. return 0;
  662. }
  663. #ifdef __cplusplus
  664. }
  665. #endif
  666. #endif //SQ_USE_TRE