sq_pcre.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. #ifdef SQ_USE_PCRE
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "squirrel.h"
  6. #include "sqstdblobimpl.h"
  7. #include <pcre.h>
  8. ////////
  9. #include "dynamic_library.h"
  10. /*SquiLu
  11. local library_functions = [
  12. ["pcre *", "pcre_compile", "const char *, int, const char **, int *, const unsigned char *"],
  13. ["pcre *", "pcre_compile2", "const char *, int, int *, const char **, int *, const unsigned char *"],
  14. ["int", "pcre_config", "int, void *"],
  15. ["int", "pcre_fullinfo", "const pcre *, const pcre_extra *, int, void *"],
  16. ["int", "pcre_dfa_exec", "const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int"],
  17. ["int", "pcre_exec", "const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int"],
  18. ["pcre_extra*", "pcre_study", "const pcre *, int, const char **"],
  19. ["void", "pcre_free_study", "pcre_extra *"],
  20. //next entry should be the last one
  21. //to make valid the test made on load_library function
  22. ["const char *", "pcre_version", "void"],
  23. ];
  24. function write_library_functions_declaration(){
  25. foreach(k,v in library_functions) {
  26. putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");");
  27. putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;");
  28. }
  29. }
  30. function write_library_functions_load(){
  31. foreach(k,v in library_functions){
  32. putsnl("dl" + v[1] + " = (" + v[1] + "_t) libdyn.dlsym(\"" + v[1] + "\");");
  33. putsnl("if(!dl" + v[1] + ") return false;");
  34. }
  35. }
  36. SquiLu*/
  37. static DynamicLibrary libdyn;
  38. //@write_library_functions_declaration();
  39. // generated-code:begin
  40. typedef pcre * (*pcre_compile_t)(const char *, int, const char **, int *, const unsigned char *);
  41. static pcre_compile_t dlpcre_compile = 0;
  42. typedef pcre * (*pcre_compile2_t)(const char *, int, int *, const char **, int *, const unsigned char *);
  43. static pcre_compile2_t dlpcre_compile2 = 0;
  44. typedef int (*pcre_config_t)(int, void *);
  45. static pcre_config_t dlpcre_config = 0;
  46. typedef int (*pcre_fullinfo_t)(const pcre *, const pcre_extra *, int, void *);
  47. static pcre_fullinfo_t dlpcre_fullinfo = 0;
  48. typedef int (*pcre_dfa_exec_t)(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int);
  49. static pcre_dfa_exec_t dlpcre_dfa_exec = 0;
  50. typedef int (*pcre_exec_t)(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int);
  51. static pcre_exec_t dlpcre_exec = 0;
  52. typedef pcre_extra* (*pcre_study_t)(const pcre *, int, const char **);
  53. static pcre_study_t dlpcre_study = 0;
  54. typedef void (*pcre_free_study_t)(pcre_extra *);
  55. static pcre_free_study_t dlpcre_free_study = 0;
  56. typedef const char * (*pcre_version_t)(void);
  57. static pcre_version_t dlpcre_version = 0;
  58. // generated-code:end
  59. static const char *dynamicLibName = DYNLIB_FOR_OS(libpcre);
  60. static bool load_library(const char *libname)
  61. {
  62. if(dlpcre_version) return true;
  63. if(libdyn.open(libname))
  64. {
  65. //@write_library_functions_load();
  66. // generated-code:begin
  67. dlpcre_compile = (pcre_compile_t) libdyn.dlsym("pcre_compile");
  68. if(!dlpcre_compile) return false;
  69. dlpcre_compile2 = (pcre_compile2_t) libdyn.dlsym("pcre_compile2");
  70. if(!dlpcre_compile2) return false;
  71. dlpcre_config = (pcre_config_t) libdyn.dlsym("pcre_config");
  72. if(!dlpcre_config) return false;
  73. dlpcre_fullinfo = (pcre_fullinfo_t) libdyn.dlsym("pcre_fullinfo");
  74. if(!dlpcre_fullinfo) return false;
  75. dlpcre_dfa_exec = (pcre_dfa_exec_t) libdyn.dlsym("pcre_dfa_exec");
  76. if(!dlpcre_dfa_exec) return false;
  77. dlpcre_exec = (pcre_exec_t) libdyn.dlsym("pcre_exec");
  78. if(!dlpcre_exec) return false;
  79. dlpcre_study = (pcre_study_t) libdyn.dlsym("pcre_study");
  80. if(!dlpcre_study) return false;
  81. dlpcre_free_study = (pcre_free_study_t) libdyn.dlsym("pcre_free_study");
  82. if(!dlpcre_free_study) return false;
  83. dlpcre_version = (pcre_version_t) libdyn.dlsym("pcre_version");
  84. if(!dlpcre_version) return false;
  85. // generated-code:end
  86. return true;
  87. }
  88. return false;
  89. }
  90. static SQInteger calc_new_size_by_max_len(SQInteger start_pos, SQInteger max_len, SQInteger curr_size)
  91. {
  92. SQInteger new_size;
  93. if(start_pos < 0)
  94. {
  95. new_size = curr_size + start_pos;
  96. start_pos = new_size < 0 ? 0 : new_size;
  97. }
  98. if(max_len > 0) new_size = start_pos + max_len;
  99. else new_size = curr_size + max_len;
  100. if( (new_size < curr_size) && (new_size > start_pos) )
  101. {
  102. return new_size;
  103. }
  104. return curr_size;
  105. }
  106. struct sqpcre_st {
  107. pcre *re;
  108. pcre_extra *re_extra;
  109. size_t ovector_size;
  110. int ovector[1];
  111. };
  112. static const SQChar PCRE_Tag[] = _SC("sqpcre");
  113. #define GET_pcre_INSTANCE() SQ_GET_INSTANCE(v, 1, sqpcre_st, PCRE_Tag) \
  114. if(self == NULL) return sq_throwerror(v, _SC("sqpcre object already closed"));
  115. static SQRESULT sq_pcre_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  116. {
  117. sqpcre_st *self = ((sqpcre_st *)p);
  118. if(self)
  119. {
  120. free(self->re);
  121. if(self->re_extra) dlpcre_free_study(self->re_extra);
  122. sq_free(self, sizeof(sqpcre_st));
  123. }
  124. return 1;
  125. }
  126. static SQRESULT sq_pcre_constructor(HSQUIRRELVM v)
  127. {
  128. if(!load_library(dynamicLibName)) return sq_throwerror(v, _SC("Failed to load libpcre !"));
  129. SQ_FUNC_VARS(v);
  130. SQ_GET_STRING(v, 2, pattern);
  131. SQ_OPT_INTEGER(v, 3, options, 0);
  132. const SQChar *error;
  133. int erroffset;
  134. pcre *re = dlpcre_compile(
  135. pattern, /* the pattern */
  136. options, /* 0 = default options */
  137. &error, /* for error message */
  138. &erroffset, /* for error offset */
  139. NULL); /* use default character tables */
  140. if(!re) return sq_throwerror(v,_SC("PCRE compilation failed at offset %d: %s"), erroffset, error);
  141. int back_ref_max;
  142. int capture_count;
  143. int rc = dlpcre_fullinfo(re, NULL, PCRE_INFO_BACKREFMAX, &back_ref_max);
  144. rc = dlpcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &capture_count);
  145. //printf("%d : %d : %d\n", __LINE__, back_ref_max, capture_count);
  146. size_t ovector_size = back_ref_max + capture_count + 1;
  147. //NP1_ASSERT(ovector_size < NP1_SIZE_T_MAX/3, "Too many back references and/or captures");
  148. ovector_size *= 3;
  149. size_t alloc_size = sizeof(sqpcre_st) + (ovector_size * sizeof(int));
  150. sqpcre_st *sqpcre = (sqpcre_st *)sq_malloc(alloc_size);
  151. sqpcre->re = re;
  152. sqpcre->re_extra = NULL;
  153. sqpcre->ovector_size = ovector_size;
  154. sq_setinstanceup(v,1,sqpcre);
  155. sq_setreleasehook(v,1,sq_pcre_releasehook);
  156. return 0;
  157. }
  158. static SQRESULT sq_pcre_study(HSQUIRRELVM v)
  159. {
  160. SQ_FUNC_VARS(v);
  161. GET_pcre_INSTANCE();
  162. SQ_OPT_INTEGER(v, 2, options, 0);
  163. const char *errptr = 0;
  164. self->re_extra = dlpcre_study(self->re, options, &errptr);
  165. sq_pushbool(v, self->re_extra != NULL);
  166. return 1;
  167. }
  168. #define OVECCOUNT 30 /* should be a multiple of 3 */
  169. static SQRESULT sq_pcre_exec(HSQUIRRELVM v)
  170. {
  171. SQ_FUNC_VARS(v);
  172. GET_pcre_INSTANCE();
  173. SQ_GET_STRING(v, 2, subject);
  174. SQ_OPT_INTEGER(v, 4, start_offset, 0);
  175. SQ_OPT_INTEGER(v, 5, options, 0);
  176. SQ_OPT_INTEGER(v, 6, max_len, 0);
  177. if(max_len)
  178. {
  179. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  180. }
  181. int rc = dlpcre_exec(
  182. self->re, /* the compiled pattern */
  183. self->re_extra, /* no extra data - we didn't study the pattern */
  184. subject, /* the subject string */
  185. subject_size, /* the length of the subject */
  186. start_offset, /* start at offset 0 in the subject */
  187. options, /* 0 = default options */
  188. self->ovector, /* output vector for substring information */
  189. self->ovector_size); /* number of elements in the output vector */
  190. const int array_pos = 3;
  191. SQInteger rtype = sq_gettype(v, array_pos);
  192. /* The output vector wasn't big enough */
  193. if (rc > 0)
  194. {
  195. if(rtype == OT_ARRAY)
  196. {
  197. int nelms = rc*2;
  198. sq_clear(v, array_pos);
  199. for (int i = 0; i < nelms; i++)
  200. {
  201. SQInteger pos = self->ovector[i];
  202. if(pos < 0) continue; //forget defined subroutines
  203. sq_pushinteger(v, pos);
  204. sq_arrayappend(v, array_pos);
  205. }
  206. }
  207. }
  208. sq_pushinteger(v, rc);
  209. return 1;
  210. }
  211. static SQRESULT sq_pcre_match(HSQUIRRELVM v)
  212. {
  213. SQ_FUNC_VARS(v);
  214. GET_pcre_INSTANCE();
  215. SQ_GET_STRING(v, 2, subject);
  216. SQ_OPT_INTEGER(v, 3, start_offset, 0);
  217. SQ_OPT_INTEGER(v, 4, options, 0);
  218. SQ_OPT_INTEGER(v, 5, max_len, 0);
  219. if(max_len)
  220. {
  221. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  222. }
  223. int rc = dlpcre_exec(
  224. self->re, /* the compiled pattern */
  225. self->re_extra, /* no extra data - we didn't study the pattern */
  226. subject, /* the subject string */
  227. subject_size, /* the length of the subject */
  228. start_offset, /* start at offset 0 in the subject */
  229. options, /* 0 = default options */
  230. self->ovector, /* output vector for substring information */
  231. self->ovector_size); /* number of elements in the output vector */
  232. if(rc > 0)
  233. {
  234. SQInteger start_pos = self->ovector[0], end_pos = self->ovector[1];
  235. if(start_pos == end_pos) sq_pushinteger(v, start_pos);
  236. else sq_pushstring(v, subject + start_pos, end_pos - start_pos);
  237. return 1;
  238. }
  239. if(rc < -2) //only no matching errore
  240. {
  241. return sq_throwerror(v, _SC("pcre2_match error %d"), (int)rc);
  242. }
  243. return 0;
  244. }
  245. static SQRESULT sq_pcre_gmatch(HSQUIRRELVM v)
  246. {
  247. SQ_FUNC_VARS(v);
  248. GET_pcre_INSTANCE();
  249. SQ_GET_STRING(v, 2, subject);
  250. SQ_OPT_INTEGER(v, 4, start_offset, 0);
  251. SQ_OPT_INTEGER(v, 5, options, 0);
  252. SQ_OPT_INTEGER(v, 6, max_len, 0);
  253. if(max_len)
  254. {
  255. subject_size = calc_new_size_by_max_len(start_offset, max_len, subject_size);
  256. }
  257. SQInteger rc;
  258. bool isFirst = true;
  259. while( (rc = dlpcre_exec(
  260. self->re, /* the compiled pattern */
  261. self->re_extra, /* no extra data - we didn't study the pattern */
  262. subject, /* the subject string */
  263. subject_size, /* the length of the subject */
  264. start_offset, /* start at offset 0 in the subject */
  265. options, /* 0 = default options */
  266. self->ovector, /* output vector for substring information */
  267. self->ovector_size)) > 0) /* number of elements in the output vector */
  268. {
  269. if(isFirst)
  270. {
  271. sq_push(v, 3); //push the function
  272. isFirst = false;
  273. }
  274. sq_pushroottable(v); //this
  275. SQInteger start_pos, end_pos, ov_offset = 0, i = 0,
  276. param_count = 1; //root table already on the stack
  277. for(;i < rc; i++) {
  278. ov_offset = i*2;
  279. start_pos = self->ovector[ov_offset];
  280. if(start_pos < 0) continue;
  281. end_pos = self->ovector[ov_offset+1];
  282. if(start_pos == end_pos) sq_pushinteger(v, start_pos);
  283. else sq_pushstring(v, subject + start_pos, end_pos - start_pos);
  284. ++param_count;
  285. }
  286. i = sq_call(v, rc+1, SQTrue, SQTrue);
  287. if(i < 0) return i;
  288. SQObjectType rtype = sq_gettype(v, -1);
  289. SQBool keep_matching = SQFalse;
  290. if(rtype == OT_BOOL) {
  291. sq_getbool(v, -1, &keep_matching);
  292. }
  293. sq_poptop(v); //remove return parameter
  294. if(!keep_matching) break;
  295. start_offset = self->ovector[(rc*2)-1]; //the last match + 1
  296. }
  297. if(rc < -2) //only no matching errore
  298. {
  299. return sq_throwerror(v, _SC("pcre2_match error %d"), (int)rc);
  300. }
  301. return 0;
  302. }
  303. #include "sqstdblobimpl.h"
  304. static SQRESULT sq_pcre_gsub(HSQUIRRELVM v)
  305. {
  306. SQ_FUNC_VARS(v);
  307. GET_pcre_INSTANCE();
  308. SQ_GET_STRING(v, 2, str);
  309. SQ_OPT_INTEGER(v, 4, options, 0);
  310. SQ_OPT_INTEGER(v, 5, max_sub, 0);
  311. if(max_sub < 0) return sq_throwerror(v, _SC("max substitutions can't be less than zero"));
  312. SQBlob blob(0,8192);
  313. const int replacement_idx = 3;
  314. SQObjectType ptype = sq_gettype(v, replacement_idx);
  315. const SQChar *replacement;
  316. SQInteger replacement_size, start_offset=0;
  317. SQInteger rc;
  318. bool isFirst = true;
  319. while( (rc = dlpcre_exec(
  320. self->re, /* the compiled pattern */
  321. self->re_extra, /* no extra data - we didn't study the pattern */
  322. str, /* the subject string */
  323. str_size, /* the length of the subject */
  324. start_offset, /* start at offset 0 in the subject */
  325. options, /* 0 = default options */
  326. self->ovector, /* output vector for substring information */
  327. self->ovector_size)) > 0) /* number of elements in the output vector */
  328. {
  329. SQInteger i, ov_offset, start_pos, end_pos;
  330. blob.Write(str+start_offset, self->ovector[0]-start_offset);
  331. switch(ptype){
  332. case OT_CLOSURE:{
  333. if(isFirst)
  334. {
  335. sq_push(v, replacement_idx); //push the function
  336. isFirst = false;
  337. }
  338. sq_pushroottable(v); //this
  339. SQInteger param_count = 1; //root table
  340. for(i=0; i < rc; i++) {
  341. ov_offset = i*2;
  342. start_pos = self->ovector[ov_offset];
  343. if(start_pos < 0) continue; //defined subroutines not pushed as parameter
  344. end_pos = self->ovector[ov_offset+1];
  345. if(start_pos == end_pos) sq_pushinteger(v, start_pos);
  346. else sq_pushstring(v, str + start_pos, end_pos - start_pos);
  347. ++param_count;
  348. }
  349. i = sq_call(v, param_count, SQTrue, SQTrue);
  350. if(i < 0) return i;
  351. if(sq_gettype(v, -1) == OT_STRING){
  352. const SQChar *svalue;
  353. sq_getstring(v, -1, &svalue);
  354. blob.Write(svalue, sq_getsize(v, -1));
  355. }
  356. sq_poptop(v);
  357. }
  358. break;
  359. case OT_ARRAY:{
  360. SQInteger array_idx = 0;
  361. for(i=0; i < rc; i++) {
  362. ov_offset = i*2;
  363. SQInteger pos = self->ovector[ov_offset];
  364. if(pos < 0) continue; //forget defined subroutines
  365. sq_pushinteger(v, array_idx++);
  366. if(SQ_SUCCEEDED(sq_get(v, replacement_idx)) &&
  367. SQ_SUCCEEDED(sq_getstr_and_size(v, -1, &replacement, &replacement_size))){
  368. blob.Write(replacement, replacement_size);
  369. sq_pop(v, 1); //remove value
  370. }
  371. }
  372. }
  373. break;
  374. case OT_TABLE:{
  375. for(i=0; i < rc; i++) {
  376. ov_offset = i*2;
  377. start_pos = self->ovector[ov_offset];
  378. if(start_pos < 0) continue;
  379. end_pos = self->ovector[ov_offset+1];
  380. sq_pushstring(v, str + start_pos, end_pos - start_pos);
  381. if(SQ_SUCCEEDED(sq_get(v, replacement_idx)) &&
  382. SQ_SUCCEEDED(sq_getstr_and_size(v, -1, &replacement, &replacement_size))){
  383. blob.Write(replacement, replacement_size);
  384. sq_pop(v, 1); //remove value
  385. }
  386. }
  387. }
  388. break;
  389. case OT_STRING:{
  390. sq_getstr_and_size(v, replacement_idx, &replacement, &replacement_size);
  391. for(i=0; i < replacement_size; i++) {
  392. SQInteger c = replacement[i];
  393. switch(c)
  394. {
  395. case '$':
  396. ++i;
  397. if(i < replacement_size)
  398. {
  399. SQInteger idx = replacement[i] - '0', match_idx = 0;
  400. for(int j=0; j < rc; j++) {
  401. ov_offset = j*2;
  402. start_pos = self->ovector[ov_offset];
  403. if(start_pos < 0) continue;
  404. if(match_idx == idx)
  405. {
  406. end_pos = self->ovector[ov_offset+1];
  407. blob.Write(str+start_pos, end_pos-start_pos);
  408. break;
  409. }
  410. ++match_idx;
  411. }
  412. if(idx != match_idx)
  413. {
  414. return sq_throwerror(v, _SC("there is no match for replacement $%d"), idx);
  415. }
  416. continue;
  417. }
  418. else
  419. {
  420. return sq_throwerror(v, _SC("unexpected end of replacement string"));
  421. }
  422. break;
  423. case '\\':
  424. ++i;
  425. if(i < replacement_size)
  426. {
  427. blob.WriteChar(replacement[i]);
  428. continue;
  429. }
  430. //falthrough last character on replacement string
  431. default:
  432. blob.WriteChar(c);
  433. }
  434. }
  435. }
  436. break;
  437. default:
  438. return sq_throwerror(v, _SC("gsub only works with closure, array, table for replacement"));
  439. }
  440. start_offset = self->ovector[(rc*2)-1]; //the last match + 1
  441. if(max_sub)
  442. {
  443. if(--max_sub == 0) break;
  444. }
  445. }
  446. if(rc < -2) //only no matching errore
  447. {
  448. return sq_throwerror(v, _SC("pcre_match error %d"), (int)rc);
  449. }
  450. if(str_size) blob.Write(str+start_offset, str_size-start_offset);
  451. sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len());
  452. return 1;
  453. }
  454. static SQRESULT sq_pcre__typeof(HSQUIRRELVM v)
  455. {
  456. sq_pushstring(v,_SC("sqpcre"),-1);
  457. return 1;
  458. }
  459. static SQRESULT sq_pcre_version(HSQUIRRELVM v)
  460. {
  461. sq_pushstring(v, dlpcre_version(),-1);
  462. return 1;
  463. }
  464. static SQRESULT sq_pcre_loadlib(HSQUIRRELVM v)
  465. {
  466. SQ_FUNC_VARS_NO_TOP(v);
  467. SQ_GET_STRING(v, 2, libname);
  468. sq_pushbool(v, load_library(libname));
  469. return 1;
  470. }
  471. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_pcre_##name,nparams,tycheck}
  472. static SQRegFunction sq_pcre_methods[] =
  473. {
  474. _DECL_FUNC(constructor,-2,_SC(".sn")),
  475. _DECL_FUNC(study,-1,_SC("xn")),
  476. _DECL_FUNC(exec,-3,_SC("xsannn")),
  477. _DECL_FUNC(match,-2,_SC("xsnnn")),
  478. _DECL_FUNC(gmatch,-3,_SC("xscnnn")),
  479. _DECL_FUNC(gsub,-3,_SC("xs s|c|a|t nn")),
  480. _DECL_FUNC(_typeof,1,_SC("x")),
  481. _DECL_FUNC(version,1,_SC(".")),
  482. _DECL_FUNC(loadlib,2,_SC(".s")),
  483. {0,0}
  484. };
  485. #undef _DECL_FUNC
  486. typedef struct {
  487. const SQChar *Str;
  488. SQInteger Val;
  489. } KeyIntType, * KeyIntPtrType;
  490. static KeyIntType sqpcre_constants[] = {
  491. #define MK_CONST(c) {_SC(#c), PCRE_##c}
  492. #define MK_CONST2(c) {_SC(c), (SQInteger)PCRE_##c}
  493. //MK_CONST(SSL_SESSION_ID_SIZE),
  494. MK_CONST(ANCHORED),
  495. MK_CONST(NOTBOL),
  496. MK_CONST(NOTEOL),
  497. MK_CONST(NOTEMPTY),
  498. MK_CONST(NOTEMPTY_ATSTART),
  499. MK_CONST(NO_START_OPTIMIZE),
  500. MK_CONST(PARTIAL_HARD),
  501. MK_CONST(PARTIAL_SOFT),
  502. MK_CONST(NEWLINE_CR),
  503. MK_CONST(NEWLINE_LF),
  504. MK_CONST(NEWLINE_CRLF),
  505. MK_CONST(NEWLINE_ANYCRLF),
  506. MK_CONST(NEWLINE_ANY),
  507. MK_CONST(NO_UTF8_CHECK),
  508. MK_CONST(STUDY_JIT_COMPILE),
  509. MK_CONST(STUDY_JIT_PARTIAL_HARD_COMPILE),
  510. MK_CONST(STUDY_JIT_PARTIAL_SOFT_COMPILE),
  511. {0,0}
  512. };
  513. #ifdef __cplusplus
  514. extern "C" {
  515. #endif
  516. SQRESULT sqext_register_pcre(HSQUIRRELVM v)
  517. {
  518. sq_pushstring(v,PCRE_Tag,-1);
  519. sq_newclass(v,SQFalse);
  520. sq_settypetag(v,-1,(void*)PCRE_Tag);
  521. sq_insert_reg_funcs(v, sq_pcre_methods);
  522. //add constants
  523. KeyIntPtrType KeyIntPtr;
  524. for (KeyIntPtr = sqpcre_constants; KeyIntPtr->Str; KeyIntPtr++) {
  525. sq_pushstring(v, KeyIntPtr->Str, -1); //first the key
  526. sq_pushinteger(v, KeyIntPtr->Val); //then the value
  527. sq_newslot(v, -3, SQFalse); //store then
  528. }
  529. sq_newslot(v,-3,SQTrue);
  530. return 0;
  531. }
  532. #ifdef __cplusplus
  533. }
  534. #endif
  535. #endif //SQ_USE_PCRE