mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-25 02:33:34 +08:00
Use POSIX regcomp/regexec.
A temporary measure, since POSIX regexes (a) don't have the same syntax as javascript's regexes, and (b) don't work on UTF-8 (unless the setlocale crap is configured correctly, and the implementation supports it), and (c) doesn't work on windows.
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
#include "jsvalue.h"
|
||||
#include "jsrun.h"
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
static void jsG_markobject(js_State *J, int mark, js_Object *obj);
|
||||
|
||||
static void jsG_freeenvironment(js_State *J, js_Environment *env)
|
||||
@@ -42,6 +44,10 @@ static void jsG_freeobject(js_State *J, js_Object *obj)
|
||||
{
|
||||
if (obj->head)
|
||||
jsG_freeproperty(J, obj->head);
|
||||
if (obj->type == JS_CREGEXP) {
|
||||
regfree(obj->u.r.prog);
|
||||
free(obj->u.r.prog);
|
||||
}
|
||||
if (obj->type == JS_CITERATOR)
|
||||
jsG_freeiterator(J, obj->u.iter.head);
|
||||
free(obj);
|
||||
|
||||
@@ -44,6 +44,8 @@ void js_dup(js_State *J);
|
||||
void js_rot2(js_State *J);
|
||||
void js_rot3(js_State *J);
|
||||
|
||||
int js_RegExp_prototype_exec(js_State *J, int idx, const char *text);
|
||||
|
||||
/* Exception handling */
|
||||
|
||||
struct js_Jumpbuf
|
||||
|
||||
+70
-4
@@ -2,12 +2,72 @@
|
||||
#include "jsvalue.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#define nelem(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
int js_RegExp_prototype_exec(js_State *J, int idx, const char *text)
|
||||
{
|
||||
int flags, opts;
|
||||
regex_t *prog;
|
||||
regmatch_t m[10];
|
||||
char *s;
|
||||
int i, n;
|
||||
|
||||
prog = js_toregexp(J, idx, &flags);
|
||||
|
||||
opts = REG_EXTENDED;
|
||||
if (flags & JS_REGEXP_I) opts |= REG_ICASE;
|
||||
if (flags & JS_REGEXP_M) opts |= REG_NEWLINE;
|
||||
|
||||
if (!regexec(prog, text, nelem(m), m, opts)) {
|
||||
js_newarray(J);
|
||||
|
||||
s = malloc(strlen(text) + 1);
|
||||
if (js_try(J)) {
|
||||
free(s);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
for (i = 0; i < nelem(m) && m[i].rm_so >= 0; ++i) {
|
||||
n = m[i].rm_eo - m[i].rm_so;
|
||||
memcpy(s, text + m[i].rm_so, n);
|
||||
s[n] = 0;
|
||||
js_pushstring(J, s);
|
||||
js_setindex(J, -2, i);
|
||||
}
|
||||
|
||||
js_endtry(J);
|
||||
free(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
js_pushnull(J);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void js_newregexp(js_State *J, const char *pattern, int flags)
|
||||
{
|
||||
char msg[256];
|
||||
js_Object *obj;
|
||||
regex_t *prog;
|
||||
int opts, status;
|
||||
|
||||
obj = jsV_newobject(J, JS_CREGEXP, J->RegExp_prototype);
|
||||
obj->u.r.prog = NULL;
|
||||
|
||||
opts = REG_EXTENDED;
|
||||
if (flags & JS_REGEXP_I) opts |= REG_ICASE;
|
||||
if (flags & JS_REGEXP_M) opts |= REG_NEWLINE;
|
||||
|
||||
prog = malloc(sizeof (regex_t));
|
||||
status = regcomp(prog, pattern, opts);
|
||||
if (status) {
|
||||
free(prog);
|
||||
regerror(status, prog, msg, sizeof msg);
|
||||
js_syntaxerror(J, "%s", msg);
|
||||
}
|
||||
|
||||
obj->u.r.prog = prog;
|
||||
obj->u.r.flags = flags;
|
||||
js_pushobject(J, obj);
|
||||
|
||||
@@ -106,13 +166,19 @@ static int Rp_toString(js_State *J, int argc)
|
||||
|
||||
static int Rp_exec(js_State *J, int argc)
|
||||
{
|
||||
js_pushnull(J);
|
||||
return 1;
|
||||
return js_RegExp_prototype_exec(J, 0, js_tostring(J, 1));
|
||||
}
|
||||
|
||||
static int Rp_test(js_State *J, int argc)
|
||||
{
|
||||
js_pushboolean(J, 0);
|
||||
int flags;
|
||||
regex_t *prog;
|
||||
const char *text;
|
||||
|
||||
prog = js_toregexp(J, 0, &flags);
|
||||
text = js_tostring(J, 1);
|
||||
|
||||
js_pushboolean(J, !regexec(prog, text, 0, NULL, 0));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+49
-3
@@ -3,6 +3,8 @@
|
||||
#include "jsbuiltin.h"
|
||||
#include "utf.h"
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
static int jsB_new_String(js_State *J, int argc)
|
||||
{
|
||||
js_newstring(J, argc > 0 ? js_tostring(J, 1) : "");
|
||||
@@ -301,6 +303,50 @@ static int S_fromCharCode(js_State *J, int argc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Sp_match(js_State *J, int argc)
|
||||
{
|
||||
const char *text;
|
||||
|
||||
text = js_tostring(J, 0);
|
||||
|
||||
if (js_isregexp(J, 1))
|
||||
js_copy(J, 1);
|
||||
else if (js_isundefined(J, 1))
|
||||
js_newregexp(J, "", 0);
|
||||
else
|
||||
js_newregexp(J, js_tostring(J, 1), 0);
|
||||
|
||||
// TODO: JS_REGEXP_G looping
|
||||
|
||||
return js_RegExp_prototype_exec(J, -1, text);
|
||||
}
|
||||
|
||||
static int Sp_search(js_State *J, int argc)
|
||||
{
|
||||
const char *text;
|
||||
regmatch_t m;
|
||||
regex_t *prog;
|
||||
int flags;
|
||||
|
||||
text = js_tostring(J, 0);
|
||||
|
||||
if (js_isregexp(J, 1))
|
||||
js_copy(J, 1);
|
||||
else if (js_isundefined(J, 1))
|
||||
js_newregexp(J, "", 0);
|
||||
else
|
||||
js_newregexp(J, js_tostring(J, 1), 0);
|
||||
|
||||
prog = js_toregexp(J, -1, &flags);
|
||||
|
||||
if (!regexec(prog, text, 1, &m, 0))
|
||||
js_pushnumber(J, m.rm_so); // TODO: convert to utf-8 index offset
|
||||
else
|
||||
js_pushnumber(J, -1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void jsB_initstring(js_State *J)
|
||||
{
|
||||
J->String_prototype->u.string = "";
|
||||
@@ -315,10 +361,10 @@ void jsB_initstring(js_State *J)
|
||||
jsB_propf(J, "indexOf", Sp_indexOf, 1);
|
||||
jsB_propf(J, "lastIndexOf", Sp_lastIndexOf, 1);
|
||||
jsB_propf(J, "localeCompare", Sp_localeCompare, 1);
|
||||
jsB_propf(J, "slice", Sp_slice, 2);
|
||||
// match (uses regexp)
|
||||
jsB_propf(J, "match", Sp_match, 1);
|
||||
// replace (uses regexp)
|
||||
// search (uses regexp)
|
||||
jsB_propf(J, "search", Sp_search, 1);
|
||||
jsB_propf(J, "slice", Sp_slice, 2);
|
||||
// split (uses regexp)
|
||||
jsB_propf(J, "substring", Sp_substring, 2);
|
||||
jsB_propf(J, "toLowerCase", Sp_toLowerCase, 0);
|
||||
|
||||
Reference in New Issue
Block a user