Compare commits

...

5 Commits

Author SHA1 Message Date
Alec Murphy
d4349b4971 deps: Update CFLAGS for openlibm build 2026-03-24 07:47:49 -04:00
Alec Murphy
c00e96e9a4 Bump VERSION to commit 7368c02 2026-03-24 07:45:47 -04:00
Alec Murphy
72d6dccbe8 Bump VERSION to commit 76bd203 2026-03-12 07:29:52 -04:00
Alec Murphy
1bc618fa9a Bump VERSION to commit 32064e1 2026-03-02 09:46:12 -05:00
Alec Murphy
5d216e3e65 Change build settings back to vscodium 2026-01-31 14:23:20 -05:00
18 changed files with 136 additions and 121 deletions

View File

@@ -1,47 +0,0 @@
[Buildset]
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x08\x00m\x00u\x00j\x00s)
[CustomBuildSystem]
CurrentConfiguration=BuildConfig0
[CustomBuildSystem][BuildConfig0]
BuildDir=file:///home/alec/repos/mujs
Title=
[CustomBuildSystem][BuildConfig0][ToolBuild]
Arguments=/home/alec/repos/mujs
Enabled=true
Environment=
Executable=file:///home/alec/repos/mujs/scripts/build-all
Type=0
[CustomBuildSystem][BuildConfig0][ToolClean]
Arguments=
Enabled=false
Environment=
Executable=
Type=3
[CustomBuildSystem][BuildConfig0][ToolConfigure]
Arguments=
Enabled=false
Environment=
Executable=
Type=1
[CustomBuildSystem][BuildConfig0][ToolInstall]
Arguments=
Enabled=false
Environment=
Executable=
Type=2
[CustomBuildSystem][BuildConfig0][ToolPrune]
Arguments=
Enabled=false
Environment=
Executable=
Type=4
[Project]
VersionControlSupport=kdevgit

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"jaktLanguageServer.compiler.executablePath": "/home/alec/cloned/jakt/build/bin/jakt",
"git.ignoreLimitWarning": true,
"terminal.integrated.shellIntegration.history": 0
}

1
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1 @@
{"version":"2.0.0","tasks":[{"label":"Build All","type":"shell","command":"${workspaceFolder}/scripts/build-all ${workspaceFolder}","group":{"kind":"build","isDefault":true},"runOptions":{"instanceLimit":1,"instancePolicy":"terminateOldest"},"problemMatcher":[]}]}

View File

@@ -1,4 +0,0 @@
[Project]
CreatedFrom=
Manager=KDevCustomBuildSystem
Name=mujs

1
src/mujs/VERSION Normal file
View File

@@ -0,0 +1 @@
commit 7368c02b4409107ed64aea19a1c32e6852c76d66

View File

@@ -240,7 +240,7 @@ static void Ap_slice(js_State *J)
static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b) static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b)
{ {
js_Object *obj = js_tovalue(J, 0)->u.object; js_Object *obj = js_tovalue(J, 0)->u.object;
if (obj->u.a.simple) { if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
js_Value *val_a = &obj->u.a.array[idx_a]; js_Value *val_a = &obj->u.a.array[idx_a];
js_Value *val_b = &obj->u.a.array[idx_b]; js_Value *val_b = &obj->u.a.array[idx_b];
int und_a = val_a->t.type == JS_TUNDEFINED; int und_a = val_a->t.type == JS_TUNDEFINED;
@@ -326,7 +326,7 @@ static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b)
static void Ap_sort_swap(js_State *J, int idx_a, int idx_b) static void Ap_sort_swap(js_State *J, int idx_a, int idx_b)
{ {
js_Object *obj = js_tovalue(J, 0)->u.object; js_Object *obj = js_tovalue(J, 0)->u.object;
if (obj->u.a.simple) { if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
js_Value tmp = obj->u.a.array[idx_a]; js_Value tmp = obj->u.a.array[idx_a];
obj->u.a.array[idx_a] = obj->u.a.array[idx_b]; obj->u.a.array[idx_a] = obj->u.a.array[idx_b];
obj->u.a.array[idx_b] = tmp; obj->u.a.array[idx_b] = tmp;
@@ -354,7 +354,7 @@ static int Ap_sort_leaf(js_State *J, int i, int end)
int lc = (j << 1) + 1; /* left child */ int lc = (j << 1) + 1; /* left child */
int rc = (j << 1) + 2; /* right child */ int rc = (j << 1) + 2; /* right child */
while (rc < end) { while (rc < end) {
if (Ap_sort_cmp(J, rc, lc) > 0) if (Ap_sort_cmp(J, lc, rc) <= 0)
j = rc; j = rc;
else else
j = lc; j = lc;
@@ -369,8 +369,9 @@ static int Ap_sort_leaf(js_State *J, int i, int end)
static void Ap_sort_sift(js_State *J, int i, int end) static void Ap_sort_sift(js_State *J, int i, int end)
{ {
int j = Ap_sort_leaf(J, i, end); int j = Ap_sort_leaf(J, i, end);
while (Ap_sort_cmp(J, i, j) > 0) while (j > i && Ap_sort_cmp(J, i, j) > 0) {
j = (j - 1) >> 1; /* parent */ j = (j - 1) >> 1; /* parent */
}
while (j > i) { while (j > i) {
Ap_sort_swap(J, i, j); Ap_sort_swap(J, i, j);
j = (j - 1) >> 1; /* parent */ j = (j - 1) >> 1; /* parent */

View File

@@ -53,6 +53,13 @@ static void Ep_toString(js_State *J)
} }
} }
static void Ep_get_stack(js_State *J)
{
Ep_toString(J);
js_getproperty(J, 0, "stackTrace");
js_concat(J);
}
static int jsB_ErrorX(js_State *J, js_Object *prototype) static int jsB_ErrorX(js_State *J, js_Object *prototype)
{ {
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype)); js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
@@ -61,7 +68,7 @@ static int jsB_ErrorX(js_State *J, js_Object *prototype)
js_defproperty(J, -2, "message", JS_DONTENUM); js_defproperty(J, -2, "message", JS_DONTENUM);
} }
if (jsB_stacktrace(J, 1)) if (jsB_stacktrace(J, 1))
js_defproperty(J, -2, "stack", JS_DONTENUM); js_defproperty(J, -2, "stackTrace", JS_DONTENUM);
return 1; return 1;
} }
@@ -71,7 +78,7 @@ static void js_newerrorx(js_State *J, const char *message, js_Object *prototype)
js_pushstring(J, message); js_pushstring(J, message);
js_setproperty(J, -2, "message"); js_setproperty(J, -2, "message");
if (jsB_stacktrace(J, 0)) if (jsB_stacktrace(J, 0))
js_setproperty(J, -2, "stack"); js_setproperty(J, -2, "stackTrace");
} }
#define DERROR(name, Name) \ #define DERROR(name, Name) \
@@ -105,8 +112,13 @@ void jsB_initerror(js_State *J)
{ {
js_pushobject(J, J->Error_prototype); js_pushobject(J, J->Error_prototype);
{ {
jsB_props(J, "name", "Error"); jsB_props(J, "name", "Error");
jsB_propf(J, "Error.prototype.toString", Ep_toString, 0); jsB_propf(J, "Error.prototype.toString", Ep_toString, 0);
jsB_props(J, "message", "");
js_newcfunction(J, Ep_get_stack, "stack", 0);
js_pushnull(J);
js_defaccessor(J, -3, "stack", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
} }
js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1); js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1);
js_defglobal(J, "Error", JS_DONTENUM); js_defglobal(J, "Error", JS_DONTENUM);

View File

@@ -270,6 +270,9 @@ struct js_State
js_Object *gcroot; /* gc scan list */ js_Object *gcroot; /* gc scan list */
int runlimit;
int memlimit;
/* environments on the call stack but currently not in scope */ /* environments on the call stack but currently not in scope */
int envtop; int envtop;
js_Environment *envstack[JS_ENVLIMIT]; js_Environment *envstack[JS_ENVLIMIT];

View File

@@ -102,7 +102,7 @@ static int jsY_findkeyword(js_State *J, const char *s)
J->text = keywords[i]; J->text = keywords[i];
return TK_BREAK + i; /* first keyword + i */ return TK_BREAK + i; /* first keyword + i */
} }
J->text = js_intern(J, s); J->text = s;
return TK_IDENTIFIER; return TK_IDENTIFIER;
} }
@@ -204,14 +204,15 @@ static void textinit(js_State *J)
static void textpush(js_State *J, Rune c) static void textpush(js_State *J, Rune c)
{ {
int n; int n, newcap;
if (c == EOF) if (c == EOF)
n = 1; n = 1;
else else
n = runelen(c); n = runelen(c);
if (J->lexbuf.len + n > J->lexbuf.cap) { if (J->lexbuf.len + n > J->lexbuf.cap) {
J->lexbuf.cap = J->lexbuf.cap * 2; newcap = J->lexbuf.cap * 2;
J->lexbuf.text = js_realloc(J, J->lexbuf.text, J->lexbuf.cap); J->lexbuf.text = js_realloc(J, J->lexbuf.text, J->lexbuf.cap);
J->lexbuf.cap = newcap;
} }
if (c == EOF) if (c == EOF)
J->lexbuf.text[J->lexbuf.len++] = 0; J->lexbuf.text[J->lexbuf.len++] = 0;
@@ -449,7 +450,7 @@ static int lexstring(js_State *J)
s = textend(J); s = textend(J);
J->text = js_intern(J, s); J->text = s;
return TK_STRING; return TK_STRING;
} }
@@ -476,7 +477,7 @@ static int isregexpcontext(int last)
static int lexregexp(js_State *J) static int lexregexp(js_State *J)
{ {
const char *s; const char *s;
int g, m, i; int g, m, i, flags;
int inclass = 0; int inclass = 0;
/* already consumed initial '/' */ /* already consumed initial '/' */
@@ -523,11 +524,13 @@ static int lexregexp(js_State *J)
if (g > 1 || i > 1 || m > 1) if (g > 1 || i > 1 || m > 1)
jsY_error(J, "duplicated flag in regular expression"); jsY_error(J, "duplicated flag in regular expression");
J->text = js_intern(J, s); J->text = s;
J->number = 0;
if (g) J->number += JS_REGEXP_G; flags = 0;
if (i) J->number += JS_REGEXP_I; if (g) flags |= JS_REGEXP_G;
if (m) J->number += JS_REGEXP_M; if (i) flags |= JS_REGEXP_I;
if (m) flags |= JS_REGEXP_M;
J->number = flags;
return TK_REGEXP; return TK_REGEXP;
} }
@@ -828,7 +831,7 @@ static int lexjsonstring(js_State *J)
s = textend(J); s = textend(J);
J->text = js_intern(J, s); J->text = s;
return TK_STRING; return TK_STRING;
} }

View File

@@ -280,51 +280,59 @@ static void O_defineProperty(js_State *J)
js_copy(J, 1); js_copy(J, 1);
} }
static void O_defineProperties_walk(js_State *J, js_Property *ref) static int O_defineProperties_walk(js_State *J, js_Property *ref, int i)
{ {
if (ref->left->level) if (ref->left->level)
O_defineProperties_walk(J, ref->left); i = O_defineProperties_walk(J, ref->left, i);
if (!(ref->atts & JS_DONTENUM)) { if (!(ref->atts & JS_DONTENUM)) {
js_pushvalue(J, ref->value); if (ref->value.t.type != JS_TOBJECT)
ToPropertyDescriptor(J, js_toobject(J, 1), ref->name, js_toobject(J, -1)); js_typeerror(J, "not an object");
js_pop(J, 1); js_pushstring(J, ref->name);
js_setindex(J, -2, i++);
} }
if (ref->right->level) if (ref->right->level)
O_defineProperties_walk(J, ref->right); i = O_defineProperties_walk(J, ref->right, i);
return i;
}
static void O_defineProperties_imp(js_State *J, js_Object *obj)
{
js_Object *props;
const char *name;
int i, n;
if (!js_isobject(J, 2)) js_typeerror(J, "not an object");
props = js_toobject(J, 2);
if (props->properties->level) {
js_newarray(J);
n = O_defineProperties_walk(J, props->properties, 0);
for (i = 0; i < n; ++i) {
js_getindex(J, -1, i);
name = js_tostring(J, -1);
if (js_hasproperty(J, 2, name)) {
ToPropertyDescriptor(J, obj, name, js_toobject(J, -1));
js_pop(J, 1);
}
js_pop(J, 1);
}
js_pop(J, 1);
}
} }
static void O_defineProperties(js_State *J) static void O_defineProperties(js_State *J)
{ {
js_Object *props; js_Object *obj;
if (!js_isobject(J, 1)) js_typeerror(J, "not an object"); if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
if (!js_isobject(J, 2)) js_typeerror(J, "not an object"); obj = js_toobject(J, 1);
O_defineProperties_imp(J, obj);
props = js_toobject(J, 2);
if (props->properties->level)
O_defineProperties_walk(J, props->properties);
js_copy(J, 1); js_copy(J, 1);
} }
static void O_create_walk(js_State *J, js_Object *obj, js_Property *ref)
{
if (ref->left->level)
O_create_walk(J, obj, ref->left);
if (!(ref->atts & JS_DONTENUM)) {
if (ref->value.t.type != JS_TOBJECT)
js_typeerror(J, "not an object");
ToPropertyDescriptor(J, obj, ref->name, ref->value.u.object);
}
if (ref->right->level)
O_create_walk(J, obj, ref->right);
}
static void O_create(js_State *J) static void O_create(js_State *J)
{ {
js_Object *obj; js_Object *obj;
js_Object *proto; js_Object *proto;
js_Object *props;
if (js_isobject(J, 1)) if (js_isobject(J, 1))
proto = js_toobject(J, 1); proto = js_toobject(J, 1);
@@ -337,11 +345,7 @@ static void O_create(js_State *J)
js_pushobject(J, obj); js_pushobject(J, obj);
if (js_isdefined(J, 2)) { if (js_isdefined(J, 2)) {
if (!js_isobject(J, 2)) O_defineProperties_imp(J, obj);
js_typeerror(J, "not an object");
props = js_toobject(J, 2);
if (props->properties->level)
O_create_walk(J, obj, props->properties);
} }
} }

View File

@@ -45,7 +45,6 @@ static void jsonexpect(js_State *J, int t)
static void jsonvalue(js_State *J) static void jsonvalue(js_State *J)
{ {
int i; int i;
const char *name;
switch (J->lookahead) { switch (J->lookahead) {
case TK_STRING: case TK_STRING:
@@ -66,11 +65,12 @@ static void jsonvalue(js_State *J)
do { do {
if (J->lookahead != TK_STRING) if (J->lookahead != TK_STRING)
js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead)); js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead));
name = J->text; js_pushstring(J, J->text);
jsonnext(J); jsonnext(J);
jsonexpect(J, ':'); jsonexpect(J, ':');
jsonvalue(J); jsonvalue(J);
js_setproperty(J, -2, name); js_setproperty(J, -3, js_tostring(J, -2));
js_pop(J, 1);
} while (jsonaccept(J, ',')); } while (jsonaccept(J, ','));
jsonexpect(J, '}'); jsonexpect(J, '}');
break; break;

View File

@@ -99,7 +99,7 @@ static js_Ast *jsP_list(js_Ast *head)
static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s) static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s)
{ {
js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0); js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);
node->string = s; node->string = js_intern(J, s);
return node; return node;
} }

View File

@@ -35,9 +35,29 @@ static void js_outofmemory(js_State *J)
js_throw(J); js_throw(J);
} }
static void js_runlimit(js_State *J)
{
STACK[TOP].t.type = JS_TLITSTR;
STACK[TOP].u.litstr = "script ran too long";
++TOP;
js_throw(J);
}
void js_setlimit(js_State *J, int runlimit, int memlimit)
{
J->runlimit = runlimit;
J->memlimit = memlimit;
}
void *js_malloc(js_State *J, int size) void *js_malloc(js_State *J, int size)
{ {
void *ptr = J->alloc(J->actx, NULL, size); void *ptr;
if (J->memlimit > 0) {
if (size >= J->memlimit)
js_outofmemory(J);
J->memlimit -= size;
}
ptr = J->alloc(J->actx, NULL, size);
if (!ptr) if (!ptr)
js_outofmemory(J); js_outofmemory(J);
return ptr; return ptr;
@@ -45,6 +65,12 @@ void *js_malloc(js_State *J, int size)
void *js_realloc(js_State *J, void *ptr, int size) void *js_realloc(js_State *J, void *ptr, int size)
{ {
if (J->memlimit > 0) {
// TODO: track released memory
if (size >= J->memlimit)
js_outofmemory(J);
J->memlimit -= size;
}
ptr = J->alloc(J->actx, ptr, size); ptr = J->alloc(J->actx, ptr, size);
if (!ptr) if (!ptr)
js_outofmemory(J); js_outofmemory(J);
@@ -61,6 +87,7 @@ char *js_strdup(js_State *J, const char *s)
void js_free(js_State *J, void *ptr) void js_free(js_State *J, void *ptr)
{ {
// TODO: track released memory (J->memlimit)
J->alloc(J->actx, ptr, 0); J->alloc(J->actx, ptr, 0);
} }
@@ -1547,7 +1574,7 @@ static int jsR_isindex(js_State *J, int idx, int *k)
static void jsR_run(js_State *J, js_Function *F) static void jsR_run(js_State *J, js_Function *F)
{ {
js_Function **FT = F->funtab; js_Function **FT = F->funtab;
const char **VT = F->vartab-1; const char **VT = F->vartab ? F->vartab - 1 : NULL;
int lightweight = F->lightweight; int lightweight = F->lightweight;
js_Instruction *pcstart = F->code; js_Instruction *pcstart = F->code;
js_Instruction *pc = F->code; js_Instruction *pc = F->code;
@@ -1571,6 +1598,12 @@ static void jsR_run(js_State *J, js_Function *F)
pc += sizeof(str) / sizeof(*pc) pc += sizeof(str) / sizeof(*pc)
while (1) { while (1) {
if (J->runlimit > 0) {
if (J->runlimit == 1)
js_runlimit(J);
--J->runlimit;
}
if (J->gccounter > J->gcthresh) if (J->gccounter > J->gcthresh)
js_gc(J, 0); js_gc(J, 0);

View File

@@ -547,6 +547,11 @@ static void Sp_replace_regexp(js_State *J)
re->last = 0; re->last = 0;
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
loop: loop:
s = m.sub[0].sp; s = m.sub[0].sp;
n = m.sub[0].ep - m.sub[0].sp; n = m.sub[0].ep - m.sub[0].sp;
@@ -622,10 +627,6 @@ end:
js_puts(J, &sb, s + n); js_puts(J, &sb, s + n);
js_putc(J, &sb, 0); js_putc(J, &sb, 0);
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
js_pushstring(J, sb ? sb->s : ""); js_pushstring(J, sb ? sb->s : "");
js_endtry(J); js_endtry(J);
js_free(J, sb); js_free(J, sb);
@@ -647,6 +648,11 @@ static void Sp_replace_string(js_State *J)
} }
n = strlen(needle); n = strlen(needle);
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
if (js_iscallable(J, 2)) { if (js_iscallable(J, 2)) {
js_copy(J, 2); js_copy(J, 2);
js_pushundefined(J); js_pushundefined(J);
@@ -683,10 +689,6 @@ static void Sp_replace_string(js_State *J)
js_putc(J, &sb, 0); js_putc(J, &sb, 0);
} }
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
js_pushstring(J, sb ? sb->s : ""); js_pushstring(J, sb ? sb->s : "");
js_endtry(J); js_endtry(J);
js_free(J, sb); js_free(J, sb);

View File

@@ -170,7 +170,7 @@ const char *js_itoa(char *out, int v)
unsigned int a; unsigned int a;
int i = 0; int i = 0;
if (v < 0) { if (v < 0) {
a = -v; a = -(unsigned)v; /* cast to avoid -INT_MIN signed overflow UB */
*s++ = '-'; *s++ = '-';
} else { } else {
a = v; a = v;

View File

@@ -9,7 +9,7 @@ extern "C" {
#define JS_VERSION_MAJOR 1 #define JS_VERSION_MAJOR 1
#define JS_VERSION_MINOR 3 #define JS_VERSION_MINOR 3
#define JS_VERSION_PATCH 5 #define JS_VERSION_PATCH 8
#define JS_VERSION (JS_VERSION_MAJOR * 10000 + JS_VERSION_MINOR * 100 + JS_VERSION_PATCH) #define JS_VERSION (JS_VERSION_MAJOR * 10000 + JS_VERSION_MINOR * 100 + JS_VERSION_PATCH)
#define JS_CHECKVERSION(x,y,z) (JS_VERSION >= ((x) * 10000 + (y) * 100 + (z))) #define JS_CHECKVERSION(x,y,z) (JS_VERSION >= ((x) * 10000 + (y) * 100 + (z)))
@@ -56,6 +56,7 @@ void js_setreport(js_State *J, js_Report report);
js_Panic js_atpanic(js_State *J, js_Panic panic); js_Panic js_atpanic(js_State *J, js_Panic panic);
void js_freestate(js_State *J); void js_freestate(js_State *J);
void js_gc(js_State *J, int report); void js_gc(js_State *J, int report);
void js_setlimit(js_State *J, int runlimit, int memlimit);
int js_dostring(js_State *J, const char *source); int js_dostring(js_State *J, const char *source);
int js_dofile(js_State *J, const char *filename); int js_dofile(js_State *J, const char *filename);

View File

@@ -37,7 +37,7 @@ endif()
list(APPEND C_ASM_COMPILE_FLAGS "-ffp-contract=off" "-fno-fast-math" "-fno-rounding-math" "-fno-math-errno") list(APPEND C_ASM_COMPILE_FLAGS "-ffp-contract=off" "-fno-fast-math" "-fno-rounding-math" "-fno-math-errno")
list(APPEND C_ASM_COMPILE_FLAGS "-fPIC" "-std=c99" "-fno-builtin") list(APPEND C_ASM_COMPILE_FLAGS "-fPIC" "-std=c99" "-fno-builtin")
list(APPEND C_ASM_COMPILE_FLAGS "-Wall" "-Wno-implicit-function-declaration") list(APPEND C_ASM_COMPILE_FLAGS "-Wall" "-Wno-implicit-function-declaration")
list(APPEND C_ASM_COMPILE_FLAGS "-DASSEMBLER" "-D__BSD_VISIBLE" "-O3") list(APPEND C_ASM_COMPILE_FLAGS "-DASSEMBLER" "-D__BSD_VISIBLE" "-O0 --mno-red-zone --mno-mmx")
# Compiler-specific compile flags # Compiler-specific compile flags
if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")

View File

@@ -106,7 +106,7 @@ endif
# If CFLAGS does not contain a -O optimization flag, default to -O3 # If CFLAGS does not contain a -O optimization flag, default to -O3
ifeq ($(findstring -O,$(CFLAGS)),) ifeq ($(findstring -O,$(CFLAGS)),)
CFLAGS_add += -O3 CFLAGS_add += -O0 -mno-red-zone -mno-mmx
endif endif
ifneq (,$(findstring MINGW,$(OS))) ifneq (,$(findstring MINGW,$(OS)))