sq_tre.cpp 23 KB

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