example scripts update; new BUILD_MODE=CHECKMEM; patched some memory leaks
This commit is contained in:
+19
-39
@@ -46,8 +46,7 @@ fun parseMethod(scan: Scanner) {
|
|||||||
method = "";
|
method = "";
|
||||||
do {
|
do {
|
||||||
method = cat(method, char);
|
method = cat(method, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != none and isUpper(char);
|
} while char != none and isUpper(char);
|
||||||
|
|
||||||
return method, none;
|
return method, none;
|
||||||
@@ -59,16 +58,13 @@ fun parsePort(scan: Scanner) {
|
|||||||
char = scan->current();
|
char = scan->current();
|
||||||
if char == ":" and isDigit(scan->hint(1)): {
|
if char == ":" and isDigit(scan->hint(1)): {
|
||||||
|
|
||||||
scan->consume(); # Skip the ":"
|
char = scan->consume(); # Skip the ":"
|
||||||
char = scan->current();
|
|
||||||
|
|
||||||
port = 0;
|
port = 0;
|
||||||
do {
|
do {
|
||||||
digit = ord(char)
|
digit = ord(char) - ord("0");
|
||||||
- ord("0");
|
|
||||||
port = port * 10 + digit;
|
port = port * 10 + digit;
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != none and isDigit(char);
|
} while char != none and isDigit(char);
|
||||||
}
|
}
|
||||||
return port;
|
return port;
|
||||||
@@ -90,8 +86,7 @@ fun parseHost(scan: Scanner) {
|
|||||||
name = "";
|
name = "";
|
||||||
do {
|
do {
|
||||||
name = cat(name, char);
|
name = cat(name, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != none and isHostname(char);
|
} while char != none and isHostname(char);
|
||||||
|
|
||||||
port = parsePort(scan);
|
port = parsePort(scan);
|
||||||
@@ -104,8 +99,7 @@ fun parsePath(scan: Scanner) {
|
|||||||
char = scan->current();
|
char = scan->current();
|
||||||
if char != none and char == "/": {
|
if char != none and char == "/": {
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} else {
|
} else {
|
||||||
if char == none or not isPChar(char):
|
if char == none or not isPChar(char):
|
||||||
return none, "Invalid character in place of path";
|
return none, "Invalid character in place of path";
|
||||||
@@ -114,14 +108,12 @@ fun parsePath(scan: Scanner) {
|
|||||||
while char != none and isPChar(char): {
|
while char != none and isPChar(char): {
|
||||||
do {
|
do {
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != none and isPChar(char);
|
} while char != none and isPChar(char);
|
||||||
if char == none or char != "/":
|
if char == none or char != "/":
|
||||||
break;
|
break;
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -139,12 +131,9 @@ fun parseQuery(scan: Scanner) {
|
|||||||
|
|
||||||
char = scan->current();
|
char = scan->current();
|
||||||
if char != none and char == "?": {
|
if char != none and char == "?": {
|
||||||
scan->consume(); # Consume the "?"
|
|
||||||
query = "";
|
query = "";
|
||||||
while isQuery(char = scan->current()): {
|
while isQuery(char = scan->consume()):
|
||||||
query = cat(query, char);
|
query = cat(query, char);
|
||||||
scan->consume();
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
query = none;
|
query = none;
|
||||||
|
|
||||||
@@ -161,12 +150,9 @@ fun parseFragment(scan: Scanner) {
|
|||||||
|
|
||||||
char = scan->current();
|
char = scan->current();
|
||||||
if char != none and char == "#": {
|
if char != none and char == "#": {
|
||||||
scan->consume(); # Consume the "#"
|
|
||||||
fragment = "";
|
fragment = "";
|
||||||
while isFragment(char = scan->current()): {
|
while isFragment(char = scan->consume()):
|
||||||
fragment = cat(fragment, char);
|
fragment = cat(fragment, char);
|
||||||
scan->consume();
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
fragment = none;
|
fragment = none;
|
||||||
|
|
||||||
@@ -207,8 +193,7 @@ fun parseSchema(scan: Scanner) {
|
|||||||
schema = "";
|
schema = "";
|
||||||
do {
|
do {
|
||||||
schema = cat(schema, char);
|
schema = cat(schema, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while isSchema(char);
|
} while isSchema(char);
|
||||||
|
|
||||||
if char == ":":
|
if char == ":":
|
||||||
@@ -230,7 +215,7 @@ fun parseURL(scan: Scanner) {
|
|||||||
schema = parseSchema(scan);
|
schema = parseSchema(scan);
|
||||||
|
|
||||||
if followsAuthority(scan): {
|
if followsAuthority(scan): {
|
||||||
consume(scan, 2);
|
scan->consume(2);
|
||||||
|
|
||||||
host, error = parseHost(scan);
|
host, error = parseHost(scan);
|
||||||
if error != none:
|
if error != none:
|
||||||
@@ -272,14 +257,12 @@ fun parseVersion(scan: Scanner) {
|
|||||||
or scan->hint(4) != "/" or not isDigit(scan->hint(5)):
|
or scan->hint(4) != "/" or not isDigit(scan->hint(5)):
|
||||||
return none, "Invalid version token";
|
return none, "Invalid version token";
|
||||||
|
|
||||||
scan->consume(5);
|
char = scan->consume(5);
|
||||||
major = ord(scan->current())
|
major = ord(char) - ord("0");
|
||||||
- ord("0");
|
|
||||||
|
|
||||||
if scan->hint(1) != "." and isDigit(scan->hint(2)): {
|
if scan->hint(1) != "." and isDigit(scan->hint(2)): {
|
||||||
scan->consume(2);
|
char = scan->consume(2);
|
||||||
minor = ord(scan->current())
|
minor = ord(char) - ord("0");
|
||||||
- ord("0");
|
|
||||||
} else
|
} else
|
||||||
minor = 0;
|
minor = 0;
|
||||||
scan->consume();
|
scan->consume();
|
||||||
@@ -345,22 +328,19 @@ fun parse(src: String) {
|
|||||||
name = "";
|
name = "";
|
||||||
do {
|
do {
|
||||||
name = cat(name, char);
|
name = cat(name, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != ":" and char != none;
|
} while char != ":" and char != none;
|
||||||
|
|
||||||
if char == none:
|
if char == none:
|
||||||
return none, "Invalid header (missing \":\" after name)";
|
return none, "Invalid header (missing \":\" after name)";
|
||||||
scan->consume();
|
scan->consume();
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
char = scan->current();
|
|
||||||
|
|
||||||
# Header body until \r
|
# Header body until \r
|
||||||
body = "";
|
body = "";
|
||||||
do {
|
do {
|
||||||
body = cat(body, char);
|
body = cat(body, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while char != "\r" and char != none;
|
} while char != "\r" and char != none;
|
||||||
|
|
||||||
headers[name] = body;
|
headers[name] = body;
|
||||||
|
|||||||
+43
-49
@@ -3,18 +3,17 @@ scan = import("scan.noja");
|
|||||||
newScanner = scan.newScanner;
|
newScanner = scan.newScanner;
|
||||||
Scanner = scan.Scanner;
|
Scanner = scan.Scanner;
|
||||||
isDigit = scan.isDigit;
|
isDigit = scan.isDigit;
|
||||||
|
ord = string.ord;
|
||||||
|
|
||||||
fun parseString(scan: Scanner) {
|
fun parseString(scan: Scanner) {
|
||||||
|
|
||||||
assert(scan->current() == '"');
|
assert(scan->current() == '"');
|
||||||
scan->consume(); # Consume the opening "
|
char = scan->consume(); # Consume the opening "
|
||||||
|
|
||||||
temp = "";
|
temp = "";
|
||||||
char = scan->current();
|
|
||||||
while char != '"' and char != none: {
|
while char != '"' and char != none: {
|
||||||
temp = string.cat(temp, char);
|
temp = string.cat(temp, char);
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if char == none: {
|
if char == none: {
|
||||||
@@ -36,16 +35,17 @@ fun parseObject(scan: Scanner) {
|
|||||||
scan->consume();
|
scan->consume();
|
||||||
|
|
||||||
obj = {};
|
obj = {};
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
if scan->current() != '}': do {
|
if char != '}': do {
|
||||||
|
|
||||||
key, err = parseValue(scan);
|
key, err = parseValue(scan);
|
||||||
if err != none:
|
if err != none:
|
||||||
return none, err;
|
return none, err;
|
||||||
if type(key) != String:
|
if type(key) != String:
|
||||||
return none, "Object key isn't a string";
|
return none, "Object key isn't a string";
|
||||||
|
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
if scan->current() != ':':
|
if char != ':':
|
||||||
return none, "Missing ':' separator after key";
|
return none, "Missing ':' separator after key";
|
||||||
scan->consume();
|
scan->consume();
|
||||||
|
|
||||||
@@ -57,11 +57,11 @@ fun parseObject(scan: Scanner) {
|
|||||||
return none, "Duplicate key in object";
|
return none, "Duplicate key in object";
|
||||||
obj[key] = val;
|
obj[key] = val;
|
||||||
|
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
if scan->current() == '}':
|
if char == '}':
|
||||||
done = true;
|
done = true;
|
||||||
else {
|
else {
|
||||||
if scan->current() != ',':
|
if char != ',':
|
||||||
return none, "Invalid character where either ',' or '}' were expected";
|
return none, "Invalid character where either ',' or '}' were expected";
|
||||||
scan->consume(); # Consume the ","
|
scan->consume(); # Consume the ","
|
||||||
done = false;
|
done = false;
|
||||||
@@ -79,16 +79,16 @@ fun parseArray(scan: Scanner) {
|
|||||||
|
|
||||||
array = [];
|
array = [];
|
||||||
|
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
if scan->current() != ']': do {
|
if char != ']': do {
|
||||||
|
|
||||||
val, err = parseValue(scan);
|
val, err = parseValue(scan);
|
||||||
if err != none:
|
if err != none:
|
||||||
return none, err;
|
return none, err;
|
||||||
array[count(array)] = val;
|
array[count(array)] = val;
|
||||||
|
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
if scan->current() == ']':
|
if char == ']':
|
||||||
done = true;
|
done = true;
|
||||||
else {
|
else {
|
||||||
if scan->current() != ',':
|
if scan->current() != ',':
|
||||||
@@ -105,21 +105,21 @@ fun parseArray(scan: Scanner) {
|
|||||||
fun parseFalse(scan: Scanner) {
|
fun parseFalse(scan: Scanner) {
|
||||||
|
|
||||||
assert(scan->current() == 'f');
|
assert(scan->current() == 'f');
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'a':
|
if char != 'a':
|
||||||
return none, "Invalid character after 'f'";
|
return none, "Invalid character after 'f'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'l':
|
if char != 'l':
|
||||||
return none, "Invalid character after 'fa'";
|
return none, "Invalid character after 'fa'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 's':
|
if char != 's':
|
||||||
return none, "Invalid character after 'fal'";
|
return none, "Invalid character after 'fal'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'e':
|
if char != 'e':
|
||||||
return none, "Invalid character after 'fals'";
|
return none, "Invalid character after 'fals'";
|
||||||
scan->consume();
|
scan->consume();
|
||||||
|
|
||||||
@@ -129,17 +129,17 @@ fun parseFalse(scan: Scanner) {
|
|||||||
fun parseTrue(scan: Scanner) {
|
fun parseTrue(scan: Scanner) {
|
||||||
|
|
||||||
assert(scan->current() == 't');
|
assert(scan->current() == 't');
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'r':
|
if char != 'r':
|
||||||
return none, "Invalid character after 't'";
|
return none, "Invalid character after 't'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'u':
|
if char != 'u':
|
||||||
return none, "Invalid character after 'tr'";
|
return none, "Invalid character after 'tr'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'e':
|
if char != 'e':
|
||||||
return none, "Invalid character after 'tru'";
|
return none, "Invalid character after 'tru'";
|
||||||
scan->consume();
|
scan->consume();
|
||||||
|
|
||||||
@@ -149,17 +149,17 @@ fun parseTrue(scan: Scanner) {
|
|||||||
fun parseNull(scan: Scanner) {
|
fun parseNull(scan: Scanner) {
|
||||||
|
|
||||||
assert(scan->current() == 'n');
|
assert(scan->current() == 'n');
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'u':
|
if char != 'u':
|
||||||
return none, "Invalid character after 'n'";
|
return none, "Invalid character after 'n'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'l':
|
if char != 'l':
|
||||||
return none, "Invalid character after 'nu'";
|
return none, "Invalid character after 'nu'";
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
|
|
||||||
if scan->current() != 'l':
|
if char != 'l':
|
||||||
return none, "Invalid character after 'nul'";
|
return none, "Invalid character after 'nul'";
|
||||||
scan->consume();
|
scan->consume();
|
||||||
|
|
||||||
@@ -167,9 +167,8 @@ fun parseNull(scan: Scanner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun integerFromDigit(char: String) {
|
fun integerFromDigit(char: String) {
|
||||||
assert(count(char) == 1);
|
assert(isDigit(char));
|
||||||
return string.ord(char)
|
return ord(char) - ord('0');
|
||||||
- string.ord('0');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseNumber(scan: Scanner) {
|
fun parseNumber(scan: Scanner) {
|
||||||
@@ -180,9 +179,8 @@ fun parseNumber(scan: Scanner) {
|
|||||||
if char == '+' or char == '-': {
|
if char == '+' or char == '-': {
|
||||||
|
|
||||||
sign = {'+': 1, '-': -1}[char];
|
sign = {'+': 1, '-': -1}[char];
|
||||||
scan->consume();
|
|
||||||
|
|
||||||
char = scan->current();
|
char = scan->consume();
|
||||||
if not isDigit(char):
|
if not isDigit(char):
|
||||||
return none, "Invalid character after +/-";
|
return none, "Invalid character after +/-";
|
||||||
}
|
}
|
||||||
@@ -194,23 +192,20 @@ fun parseNumber(scan: Scanner) {
|
|||||||
n = integerFromDigit(char);
|
n = integerFromDigit(char);
|
||||||
temp = temp * 10 + n;
|
temp = temp * 10 + n;
|
||||||
|
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
|
|
||||||
} while isDigit(char);
|
} while isDigit(char);
|
||||||
|
|
||||||
if char == '.' and isDigit(scan->hint(1)): {
|
if char == '.' and isDigit(scan->hint(1)): {
|
||||||
|
|
||||||
scan->consume(); # Consume the dot
|
char = scan->consume(); # Consume the dot
|
||||||
char = scan->current();
|
|
||||||
|
|
||||||
q = 1.0;
|
q = 1.0;
|
||||||
do {
|
do {
|
||||||
q = q / 10;
|
q = q / 10;
|
||||||
n = integerFromDigit(char);
|
n = integerFromDigit(char);
|
||||||
temp = temp + q * n;
|
temp = temp + q * n;
|
||||||
scan->consume();
|
char = scan->consume();
|
||||||
char = scan->current();
|
|
||||||
} while isDigit(char);
|
} while isDigit(char);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,8 +235,7 @@ fun parseValue(scan: Scanner) {
|
|||||||
'9': parseNumber
|
'9': parseNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
scan->consumeSpaces();
|
char = scan->consumeSpaces();
|
||||||
char = scan->current();
|
|
||||||
if char == none: {
|
if char == none: {
|
||||||
val = none;
|
val = none;
|
||||||
err = "Source ended where a value was expected";
|
err = "Source ended where a value was expected";
|
||||||
|
|||||||
+7
-3
@@ -26,11 +26,15 @@ fun consume(scan: Scanner, n: int = 1) {
|
|||||||
assert(n > 0);
|
assert(n > 0);
|
||||||
limit = count(scan.src);
|
limit = count(scan.src);
|
||||||
scan.i = min(scan.i + n, limit);
|
scan.i = min(scan.i + n, limit);
|
||||||
|
return current(scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
fun consumeSpaces(scan: Scanner)
|
fun consumeSpaces(scan: Scanner) {
|
||||||
while isSpace(current(scan)):
|
char = current(scan);
|
||||||
consume(scan);
|
while isSpace(char):
|
||||||
|
char = consume(scan);
|
||||||
|
return char;
|
||||||
|
}
|
||||||
|
|
||||||
fun newScanner(src: String) {
|
fun newScanner(src: String) {
|
||||||
scan = {
|
scan = {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ LFLAGS = -lm
|
|||||||
# Can be one of: YES, NO
|
# Can be one of: YES, NO
|
||||||
USING_VALGRIND = NO
|
USING_VALGRIND = NO
|
||||||
|
|
||||||
# May be one of: COVERAGE, RELEASE, DEBUG
|
# May be one of: COVERAGE, RELEASE, DEBUG, CHECKMEM
|
||||||
BUILD_MODE = RELEASE
|
BUILD_MODE = RELEASE
|
||||||
|
|
||||||
# Changing the BUILD_MODE will add one of the
|
# Changing the BUILD_MODE will add one of the
|
||||||
@@ -62,6 +62,9 @@ BUILD_MODE = RELEASE
|
|||||||
CFLAGS_DEBUG = -DDEBUG -g
|
CFLAGS_DEBUG = -DDEBUG -g
|
||||||
LFLAGS_DEBUG =
|
LFLAGS_DEBUG =
|
||||||
|
|
||||||
|
CFLAGS_CHECKMEM = -fsanitize=address -g
|
||||||
|
LFLAGS_CHECKMEM = -fsanitize=address
|
||||||
|
|
||||||
CFLAGS_RELEASE = -DNDEBUG -O3
|
CFLAGS_RELEASE = -DNDEBUG -O3
|
||||||
LFLAGS_RELEASE =
|
LFLAGS_RELEASE =
|
||||||
|
|
||||||
|
|||||||
@@ -134,13 +134,18 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object
|
|||||||
UNUSED(errname);
|
UNUSED(errname);
|
||||||
|
|
||||||
Object *o_none = Object_NewNone(heap, error);
|
Object *o_none = Object_NewNone(heap, error);
|
||||||
if(o_none == NULL)
|
if(o_none == NULL) {
|
||||||
|
Source_Free(src);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
Object *o_err = Object_FromString(sub_error.message, -1, heap, error);
|
Object *o_err = Object_FromString(sub_error.message, -1, heap, error);
|
||||||
if(o_err == NULL)
|
if(o_err == NULL) {
|
||||||
|
Source_Free(src);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Source_Free(src);
|
||||||
Error_Free(&sub_error);
|
Error_Free(&sub_error);
|
||||||
rets[0] = o_none;
|
rets[0] = o_none;
|
||||||
rets[1] = o_err;
|
rets[1] = o_err;
|
||||||
@@ -156,19 +161,30 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object
|
|||||||
UNUSED(errname);
|
UNUSED(errname);
|
||||||
|
|
||||||
Object *o_none = Object_NewNone(heap, error);
|
Object *o_none = Object_NewNone(heap, error);
|
||||||
if(o_none == NULL) return -1;
|
if(o_none == NULL) {
|
||||||
|
Source_Free(src);
|
||||||
|
Executable_Free(exe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
Object *o_err = Object_FromString(sub_error.message, -1, heap, error);
|
Object *o_err = Object_FromString(sub_error.message, -1, heap, error);
|
||||||
if(o_err == NULL) return -1;
|
if(o_err == NULL) {
|
||||||
|
Source_Free(src);
|
||||||
|
Executable_Free(exe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
Error_Free(&sub_error);
|
Error_Free(&sub_error);
|
||||||
rets[0] = o_none;
|
rets[0] = o_none;
|
||||||
rets[1] = o_err;
|
rets[1] = o_err;
|
||||||
|
Source_Free(src);
|
||||||
|
Executable_Free(exe);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
ASSERT(retc == 1);
|
ASSERT(retc == 1);
|
||||||
|
|
||||||
Error_Free(&sub_error);
|
Error_Free(&sub_error);
|
||||||
|
Source_Free(src);
|
||||||
|
Executable_Free(exe);
|
||||||
rets[0] = sub_rets[0];
|
rets[0] = sub_rets[0];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user