forked from KolibriOS/kolibrios
kosjs: replace libmujs.a with sources; if argc = 0, see "usage"
git-svn-id: svn://kolibrios.org@8456 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
298
programs/develop/kosjs/libmujs/jsstate.c
Executable file
298
programs/develop/kosjs/libmujs/jsstate.c
Executable file
@@ -0,0 +1,298 @@
|
||||
#include "jsi.h"
|
||||
#include "jsparse.h"
|
||||
#include "jscompile.h"
|
||||
#include "jsvalue.h"
|
||||
#include "jsrun.h"
|
||||
#include "jsbuiltin.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void *js_defaultalloc(void *actx, void *ptr, int size)
|
||||
{
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return realloc(ptr, (size_t)size);
|
||||
}
|
||||
|
||||
static void js_defaultreport(js_State *J, const char *message)
|
||||
{
|
||||
fputs(message, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static void js_defaultpanic(js_State *J)
|
||||
{
|
||||
js_report(J, "uncaught exception");
|
||||
/* return to javascript to abort */
|
||||
}
|
||||
|
||||
int js_ploadstring(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
if (js_try(J))
|
||||
return 1;
|
||||
js_loadstring(J, filename, source);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int js_ploadfile(js_State *J, const char *filename)
|
||||
{
|
||||
if (js_try(J))
|
||||
return 1;
|
||||
js_loadfile(J, filename);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *js_trystring(js_State *J, int idx, const char *error)
|
||||
{
|
||||
const char *s;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
s = js_tostring(J, idx);
|
||||
js_endtry(J);
|
||||
return s;
|
||||
}
|
||||
|
||||
double js_trynumber(js_State *J, int idx, double error)
|
||||
{
|
||||
double v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_tonumber(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
int js_tryinteger(js_State *J, int idx, int error)
|
||||
{
|
||||
int v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_tointeger(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
int js_tryboolean(js_State *J, int idx, int error)
|
||||
{
|
||||
int v;
|
||||
if (js_try(J)) {
|
||||
js_pop(J, 1);
|
||||
return error;
|
||||
}
|
||||
v = js_toboolean(J, idx);
|
||||
js_endtry(J);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void js_loadstringx(js_State *J, const char *filename, const char *source, int iseval)
|
||||
{
|
||||
js_Ast *P;
|
||||
js_Function *F;
|
||||
|
||||
if (js_try(J)) {
|
||||
jsP_freeparse(J);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
P = jsP_parse(J, filename, source);
|
||||
F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict);
|
||||
jsP_freeparse(J);
|
||||
js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE, iseval ? JS_CEVAL : JS_CSCRIPT);
|
||||
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
void js_loadeval(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_loadstringx(J, filename, source, 1);
|
||||
}
|
||||
|
||||
void js_loadstring(js_State *J, const char *filename, const char *source)
|
||||
{
|
||||
js_loadstringx(J, filename, source, 0);
|
||||
}
|
||||
|
||||
void js_loadfile(js_State *J, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
char *s, *p;
|
||||
int n, t;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f) {
|
||||
js_error(J, "cannot open file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (fseek(f, 0, SEEK_END) < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
n = ftell(f);
|
||||
if (n < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (fseek(f, 0, SEEK_SET) < 0) {
|
||||
fclose(f);
|
||||
js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
if (js_try(J)) {
|
||||
fclose(f);
|
||||
js_throw(J);
|
||||
}
|
||||
s = js_malloc(J, n + 1); /* add space for string terminator */
|
||||
js_endtry(J);
|
||||
|
||||
t = fread(s, 1, (size_t)n, f);
|
||||
if (t != n) {
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
s[n] = 0; /* zero-terminate string containing file data */
|
||||
|
||||
if (js_try(J)) {
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_throw(J);
|
||||
}
|
||||
|
||||
/* skip first line if it starts with "#!" */
|
||||
p = s;
|
||||
if (p[0] == '#' && p[1] == '!') {
|
||||
p += 2;
|
||||
while (*p && *p != '\n')
|
||||
++p;
|
||||
}
|
||||
|
||||
js_loadstring(J, filename, p);
|
||||
|
||||
js_free(J, s);
|
||||
fclose(f);
|
||||
js_endtry(J);
|
||||
}
|
||||
|
||||
int js_dostring(js_State *J, const char *source)
|
||||
{
|
||||
if (js_try(J)) {
|
||||
js_report(J, js_trystring(J, -1, "Error"));
|
||||
js_pop(J, 1);
|
||||
return 1;
|
||||
}
|
||||
js_loadstring(J, "[string]", source);
|
||||
js_pushundefined(J);
|
||||
js_call(J, 0);
|
||||
js_pop(J, 1);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int js_dofile(js_State *J, const char *filename)
|
||||
{
|
||||
if (js_try(J)) {
|
||||
js_report(J, js_trystring(J, -1, "Error"));
|
||||
js_pop(J, 1);
|
||||
return 1;
|
||||
}
|
||||
js_loadfile(J, filename);
|
||||
js_pushundefined(J);
|
||||
js_call(J, 0);
|
||||
js_pop(J, 1);
|
||||
js_endtry(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
js_Panic js_atpanic(js_State *J, js_Panic panic)
|
||||
{
|
||||
js_Panic old = J->panic;
|
||||
J->panic = panic;
|
||||
return old;
|
||||
}
|
||||
|
||||
void js_report(js_State *J, const char *message)
|
||||
{
|
||||
if (J->report)
|
||||
J->report(J, message);
|
||||
}
|
||||
|
||||
void js_setreport(js_State *J, js_Report report)
|
||||
{
|
||||
J->report = report;
|
||||
}
|
||||
|
||||
void js_setcontext(js_State *J, void *uctx)
|
||||
{
|
||||
J->uctx = uctx;
|
||||
}
|
||||
|
||||
void *js_getcontext(js_State *J)
|
||||
{
|
||||
return J->uctx;
|
||||
}
|
||||
|
||||
js_State *js_newstate(js_Alloc alloc, void *actx, int flags)
|
||||
{
|
||||
js_State *J;
|
||||
|
||||
assert(sizeof(js_Value) == 16);
|
||||
assert(soffsetof(js_Value, type) == 15);
|
||||
|
||||
if (!alloc)
|
||||
alloc = js_defaultalloc;
|
||||
|
||||
J = alloc(actx, NULL, sizeof *J);
|
||||
if (!J)
|
||||
return NULL;
|
||||
memset(J, 0, sizeof(*J));
|
||||
J->actx = actx;
|
||||
J->alloc = alloc;
|
||||
|
||||
if (flags & JS_STRICT)
|
||||
J->strict = J->default_strict = 1;
|
||||
|
||||
J->trace[0].name = "-top-";
|
||||
J->trace[0].file = "native";
|
||||
J->trace[0].line = 0;
|
||||
|
||||
J->report = js_defaultreport;
|
||||
J->panic = js_defaultpanic;
|
||||
|
||||
J->stack = alloc(actx, NULL, JS_STACKSIZE * sizeof *J->stack);
|
||||
if (!J->stack) {
|
||||
alloc(actx, NULL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
J->gcmark = 1;
|
||||
J->nextref = 0;
|
||||
J->gcthresh = 0; /* reaches stability within ~ 2-5 GC cycles */
|
||||
|
||||
J->R = jsV_newobject(J, JS_COBJECT, NULL);
|
||||
J->G = jsV_newobject(J, JS_COBJECT, NULL);
|
||||
J->E = jsR_newenvironment(J, J->G, NULL);
|
||||
J->GE = J->E;
|
||||
|
||||
jsB_init(J);
|
||||
|
||||
return J;
|
||||
}
|
Reference in New Issue
Block a user