new curly bracket coding convention
This commit is contained in:
+39
-38
@@ -42,10 +42,10 @@ fun parse(str) {
|
||||
return none;
|
||||
}
|
||||
|
||||
return parseAnyValue(ctx);
|
||||
return parseAny(ctx);
|
||||
}
|
||||
|
||||
fun parseArrayValue(ctx) {
|
||||
fun parseArray(ctx) {
|
||||
|
||||
assert(current(ctx) == '[');
|
||||
|
||||
@@ -67,7 +67,7 @@ fun parseArrayValue(ctx) {
|
||||
|
||||
while true: {
|
||||
|
||||
child = parseAnyValue(ctx);
|
||||
child = parseAny(ctx);
|
||||
|
||||
if child == none:
|
||||
return none;
|
||||
@@ -103,7 +103,7 @@ fun parseArrayValue(ctx) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
fun parseObjectValue(ctx) {
|
||||
fun parseObject(ctx) {
|
||||
|
||||
assert(current(ctx) == '{');
|
||||
|
||||
@@ -130,7 +130,7 @@ fun parseObjectValue(ctx) {
|
||||
return none;
|
||||
}
|
||||
|
||||
key = parseStringValue(ctx);
|
||||
key = parseString(ctx);
|
||||
|
||||
if key == none:
|
||||
return none;
|
||||
@@ -146,7 +146,7 @@ fun parseObjectValue(ctx) {
|
||||
|
||||
skip(ctx, isSpace);
|
||||
|
||||
child = parseAnyValue(ctx);
|
||||
child = parseAny(ctx);
|
||||
|
||||
if child == none:
|
||||
return none;
|
||||
@@ -182,7 +182,7 @@ fun parseObjectValue(ctx) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
fun parseStringValue(ctx) {
|
||||
fun parseString(ctx) {
|
||||
|
||||
next(ctx); # Skip the '"'.
|
||||
|
||||
@@ -207,7 +207,7 @@ fun parseStringValue(ctx) {
|
||||
return buff;
|
||||
}
|
||||
|
||||
fun parseNumberValue(ctx) {
|
||||
fun parseNumber(ctx) {
|
||||
|
||||
assert(isDigit(current(ctx)));
|
||||
|
||||
@@ -251,49 +251,50 @@ fun parseNumberValue(ctx) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
fun parseAnyValue(ctx) {
|
||||
fun parseAny(ctx) {
|
||||
|
||||
print('Parsing value\n');
|
||||
|
||||
assert(not ended(ctx));
|
||||
|
||||
if current(ctx) == '[':
|
||||
return parseArrayValue(ctx);
|
||||
return parseArray(ctx);
|
||||
|
||||
if current(ctx) == '{':
|
||||
return parseObjectValue(ctx);
|
||||
return parseObject(ctx);
|
||||
|
||||
if current(ctx) == '"':
|
||||
return parseStringValue(ctx);
|
||||
return parseString(ctx);
|
||||
|
||||
if isDigit(current(ctx)):
|
||||
return parseNumberValue(ctx);
|
||||
return parseNumber(ctx);
|
||||
|
||||
error("Not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
tests = [
|
||||
'',
|
||||
'1',
|
||||
'10',
|
||||
'1.10',
|
||||
'"jeje"',
|
||||
'[]',
|
||||
'[1,2,3]',
|
||||
' [ ] ',
|
||||
' [ 1 , 2 , 3 ]',
|
||||
'{}',
|
||||
' { } ',
|
||||
'{"hoy":4}',
|
||||
' { "hoy" : 4 } ',
|
||||
'a'
|
||||
];
|
||||
#tests = ['', '1', '10', '1.10', '"jeje"', '[]', '[1,2,3]', ' [ ] ', ' [ 1 , 2 , 3 ]', '{}', ' { } ', '{"hoy":4}', ' { "hoy" : 4 } '];
|
||||
|
||||
i = 0;
|
||||
while i < count(tests): {
|
||||
r = parse(tests[i]);
|
||||
if r == none:
|
||||
print('\nTest ', i, ' failed\n');
|
||||
else
|
||||
print(tests[i], ' -> ', r, '\n');
|
||||
i = i + 1;
|
||||
}
|
||||
#i = 0;
|
||||
#while i < count(tests): {
|
||||
# r = parse(tests[i]);
|
||||
# if r == none:
|
||||
# print('\nTest ', i, ' failed\n');
|
||||
# else
|
||||
# print(tests[i], ' -> ', r, '\n');
|
||||
# i = i + 1;
|
||||
#}
|
||||
|
||||
file = files.openFile('examples/large-file.json', files.READ);
|
||||
if file == none:
|
||||
error("Failed to open file");
|
||||
|
||||
buff = newBuffer(30000000);
|
||||
if buff == none:
|
||||
error("Failed to create buffer");
|
||||
|
||||
n = files.read(file, buff);
|
||||
|
||||
text = bufferToString(sliceBuffer(buff, 0, n));
|
||||
|
||||
print(parse(text));
|
||||
|
||||
+59
-60
@@ -64,10 +64,10 @@ static Object *bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, E
|
||||
uint32_t ret = 0;
|
||||
|
||||
if(!Object_IsString(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Argument #%d is not a string", 1);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Argument #%d is not a string", 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *string;
|
||||
int n;
|
||||
@@ -76,10 +76,10 @@ static Object *bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, E
|
||||
return NULL;
|
||||
|
||||
if(n == 0)
|
||||
{
|
||||
Error_Report(error, 0, "Argument #%d is an empty string", 1);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Argument #%d is an empty string", 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int k = utf8_sequence_to_utf32_codepoint(string,n,&ret);
|
||||
@@ -111,31 +111,31 @@ static Object *bin_input(Runtime *runtime, Object **argv, unsigned int argc, Err
|
||||
int size = 0, cap = sizeof(maybe)-1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
char c = getc(stdin);
|
||||
|
||||
if(c == '\n')
|
||||
break;
|
||||
|
||||
if(size == cap)
|
||||
{
|
||||
char c = getc(stdin);
|
||||
int newcap = cap*2;
|
||||
char *tmp = realloc(str, newcap + 1);
|
||||
|
||||
if(c == '\n')
|
||||
break;
|
||||
if(tmp == NULL)
|
||||
{
|
||||
if(str != maybe) free(str);
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(size == cap)
|
||||
{
|
||||
int newcap = cap*2;
|
||||
char *tmp = realloc(str, newcap + 1);
|
||||
|
||||
if(tmp == NULL)
|
||||
{
|
||||
if(str != maybe) free(str);
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = tmp;
|
||||
cap = newcap;
|
||||
}
|
||||
|
||||
str[size++] = c;
|
||||
str = tmp;
|
||||
cap = newcap;
|
||||
}
|
||||
|
||||
str[size++] = c;
|
||||
}
|
||||
|
||||
str[size] = '\0';
|
||||
|
||||
Object *res = Object_FromString(str, size, Runtime_GetHeap(runtime), error);
|
||||
@@ -150,11 +150,11 @@ static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Er
|
||||
{
|
||||
for(unsigned int i = 0; i < argc; i += 1)
|
||||
if(!Object_ToBool(argv[i], error))
|
||||
{
|
||||
if(!error->occurred)
|
||||
Error_Report(error, 0, "Assertion failed");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
if(!error->occurred)
|
||||
Error_Report(error, 0, "Assertion failed");
|
||||
return NULL;
|
||||
}
|
||||
return Object_NewNone(Runtime_GetHeap(runtime), error);
|
||||
}
|
||||
|
||||
@@ -179,48 +179,47 @@ static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Er
|
||||
unsigned int total_count = 0;
|
||||
|
||||
for(unsigned int i = 0; i < argc; i += 1)
|
||||
{
|
||||
if(!Object_IsString(argv[i]))
|
||||
{
|
||||
if(!Object_IsString(argv[i]))
|
||||
{
|
||||
Error_Report(error, 0, "Argument #%d is not a string", i+1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_count += Object_Count(argv[i], error);
|
||||
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
Error_Report(error, 0, "Argument #%d is not a string", i+1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_count += Object_Count(argv[i], error);
|
||||
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char starting[128];
|
||||
char *buffer = starting;
|
||||
|
||||
if(total_count > sizeof(starting)-1)
|
||||
{
|
||||
buffer = malloc(total_count+1);
|
||||
{
|
||||
buffer = malloc(total_count+1);
|
||||
|
||||
if(buffer == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
if(buffer == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Object *result = NULL;
|
||||
|
||||
for(unsigned int i = 0, written = 0; i < argc; i += 1)
|
||||
{
|
||||
int n;
|
||||
const char *s;
|
||||
{
|
||||
int n;
|
||||
const char *s = Object_ToString(argv[i], &n,
|
||||
Runtime_GetHeap(runtime), error);
|
||||
|
||||
s = Object_ToString(argv[i], &n, Runtime_GetHeap(runtime), error);
|
||||
if(error->occurred)
|
||||
goto done;
|
||||
|
||||
if(error->occurred)
|
||||
goto done;
|
||||
|
||||
memcpy(buffer + written, s, n);
|
||||
written += n;
|
||||
}
|
||||
memcpy(buffer + written, s, n);
|
||||
written += n;
|
||||
}
|
||||
|
||||
buffer[total_count] = '\0';
|
||||
|
||||
|
||||
+93
-93
@@ -43,16 +43,16 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc,
|
||||
assert(argc == 2);
|
||||
|
||||
if(!Object_IsString(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!Object_IsInt(argv[1]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Heap *heap = Runtime_GetHeap(runtime);
|
||||
|
||||
@@ -71,24 +71,24 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc,
|
||||
const char *mode2;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case MD_READ:
|
||||
mode2 = "r";
|
||||
break;
|
||||
{
|
||||
case MD_READ:
|
||||
mode2 = "r";
|
||||
break;
|
||||
|
||||
case MD_READ | MD_WRITE:
|
||||
mode2 = "w+";
|
||||
break;
|
||||
case MD_READ | MD_WRITE:
|
||||
mode2 = "w+";
|
||||
break;
|
||||
|
||||
case MD_READ | MD_APPEND:
|
||||
case MD_READ | MD_WRITE | MD_APPEND:
|
||||
mode2 = "a";
|
||||
break;
|
||||
case MD_READ | MD_APPEND:
|
||||
case MD_READ | MD_WRITE | MD_APPEND:
|
||||
mode2 = "a";
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
fp = fopen(path, mode2);
|
||||
|
||||
@@ -108,16 +108,16 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro
|
||||
// Arg 2: count
|
||||
|
||||
if(!Object_IsFile(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!Object_IsBuffer(argv[1]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Heap *heap = Runtime_GetHeap(runtime);
|
||||
|
||||
@@ -129,26 +129,26 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro
|
||||
int read_size;
|
||||
|
||||
if(Object_IsNone(argv[2]))
|
||||
{
|
||||
read_size = buff_size;
|
||||
}
|
||||
{
|
||||
read_size = buff_size;
|
||||
}
|
||||
else if(Object_IsInt(argv[2]))
|
||||
{
|
||||
long long int temp = Object_ToInt(argv[2], error);
|
||||
{
|
||||
long long int temp = Object_ToInt(argv[2], error);
|
||||
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
|
||||
read_size = temp; // TODO: Handle potential overflow.
|
||||
|
||||
if(read_size > buff_size)
|
||||
read_size = buff_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read_size = temp; // TODO: Handle potential overflow.
|
||||
|
||||
if(read_size > buff_size)
|
||||
read_size = buff_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *fp = Object_ToStream(argv[0], error);
|
||||
|
||||
@@ -169,16 +169,16 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err
|
||||
// Arg 2: count
|
||||
|
||||
if(!Object_IsFile(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!Object_IsBuffer(argv[1]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Heap *heap = Runtime_GetHeap(runtime);
|
||||
|
||||
@@ -190,26 +190,26 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err
|
||||
int write_size;
|
||||
|
||||
if(Object_IsNone(argv[2]))
|
||||
{
|
||||
write_size = buff_size;
|
||||
}
|
||||
{
|
||||
write_size = buff_size;
|
||||
}
|
||||
else if(Object_IsInt(argv[2]))
|
||||
{
|
||||
long long int temp = Object_ToInt(argv[2], error);
|
||||
{
|
||||
long long int temp = Object_ToInt(argv[2], error);
|
||||
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
|
||||
write_size = temp; // TODO: Handle potential overflow.
|
||||
|
||||
if(write_size > buff_size)
|
||||
write_size = buff_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
|
||||
if(error->occurred)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
write_size = temp; // TODO: Handle potential overflow.
|
||||
|
||||
if(write_size > buff_size)
|
||||
write_size = buff_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *fp = Object_ToStream(argv[0], error);
|
||||
|
||||
@@ -228,10 +228,10 @@ static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, E
|
||||
// Arg 0: path
|
||||
|
||||
if(!Object_IsString(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Heap *heap = Runtime_GetHeap(runtime);
|
||||
|
||||
@@ -248,10 +248,10 @@ static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, E
|
||||
Object *dob = Object_FromDIR(dir, heap, error);
|
||||
|
||||
if(error->occurred)
|
||||
{
|
||||
(void) closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
(void) closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dob;
|
||||
}
|
||||
@@ -263,10 +263,10 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg
|
||||
// Arg 0: path
|
||||
|
||||
if(!Object_IsDir(argv[0]))
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DIR *dir = Object_ToDIR(argv[0], error);
|
||||
|
||||
@@ -282,15 +282,15 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg
|
||||
struct dirent *ent = readdir(dir);
|
||||
|
||||
if(ent == NULL)
|
||||
{
|
||||
if(errno == 0)
|
||||
// Nothing left to read.
|
||||
return Object_NewNone(heap, error);
|
||||
{
|
||||
if(errno == 0)
|
||||
// Nothing left to read.
|
||||
return Object_NewNone(heap, error);
|
||||
|
||||
// An error occurred.
|
||||
Error_Report(error, 1, "Failed to read directory item");
|
||||
return NULL;
|
||||
}
|
||||
// An error occurred.
|
||||
Error_Report(error, 1, "Failed to read directory item");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Object_FromString(ent->d_name, -1, heap, error);
|
||||
}
|
||||
|
||||
+45
-45
@@ -33,54 +33,54 @@
|
||||
#include "math.h"
|
||||
|
||||
#define WRAP_FUNC(name) \
|
||||
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
|
||||
{ \
|
||||
assert(argc == 1); \
|
||||
\
|
||||
if(Object_IsFloat(argv[0])) \
|
||||
{ \
|
||||
double v = Object_ToFloat(argv[0], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
|
||||
return NULL; \
|
||||
} \
|
||||
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
|
||||
{ \
|
||||
assert(argc == 1); \
|
||||
\
|
||||
if(Object_IsFloat(argv[0])) \
|
||||
{ \
|
||||
double v = Object_ToFloat(argv[0], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WRAP_FUNC_2(name) \
|
||||
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
|
||||
{ \
|
||||
assert(argc == 2); \
|
||||
\
|
||||
if(!Object_IsFloat(argv[0])) \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if(!Object_IsFloat(argv[1])) \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
double v1 = Object_ToFloat(argv[0], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
double v2 = Object_ToFloat(argv[1], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \
|
||||
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
|
||||
{ \
|
||||
assert(argc == 2); \
|
||||
\
|
||||
if(!Object_IsFloat(argv[0])) \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if(!Object_IsFloat(argv[1])) \
|
||||
{ \
|
||||
Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
double v1 = Object_ToFloat(argv[0], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
double v2 = Object_ToFloat(argv[1], error); \
|
||||
\
|
||||
if(error->occurred) \
|
||||
return NULL; \
|
||||
\
|
||||
return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \
|
||||
}
|
||||
|
||||
WRAP_FUNC(ceil)
|
||||
|
||||
+167
-169
@@ -131,51 +131,51 @@ void Executable_Free(Executable *exe)
|
||||
assert(exe->refs >= 0);
|
||||
|
||||
if(exe->refs == 0)
|
||||
{
|
||||
if(exe->src)
|
||||
Source_Free(exe->src);
|
||||
free(exe);
|
||||
}
|
||||
{
|
||||
if(exe->src)
|
||||
Source_Free(exe->src);
|
||||
free(exe);
|
||||
}
|
||||
}
|
||||
|
||||
void Executable_Dump(Executable *exe)
|
||||
{
|
||||
for(int i = 0; i < exe->bodyl; i += 1)
|
||||
{
|
||||
Opcode opcode;
|
||||
Operand ops[MAX_OPS];
|
||||
int opc = MAX_OPS;
|
||||
|
||||
(void) Executable_Fetch(exe, i, &opcode, ops, &opc);
|
||||
|
||||
const InstrInfo *info = instr_table + exe->body[i].opcode;
|
||||
|
||||
fprintf(stderr, "%d: %s ", i, info->name);
|
||||
|
||||
for(int j = 0; j < opc; j += 1)
|
||||
{
|
||||
Opcode opcode;
|
||||
Operand ops[MAX_OPS];
|
||||
int opc = MAX_OPS;
|
||||
switch(ops[j].type)
|
||||
{
|
||||
case OPTP_INT:
|
||||
fprintf(stderr, "%lld ", ops[j].as_int);
|
||||
break;
|
||||
|
||||
(void) Executable_Fetch(exe, i, &opcode, ops, &opc);
|
||||
case OPTP_FLOAT:
|
||||
fprintf(stderr, "%f ", ops[j].as_float);
|
||||
break;
|
||||
|
||||
const InstrInfo *info = instr_table + exe->body[i].opcode;
|
||||
case OPTP_STRING:
|
||||
fprintf(stderr, "[%s] ", ops[j].as_string);
|
||||
break;
|
||||
|
||||
fprintf(stderr, "%d: %s ", i, info->name);
|
||||
|
||||
for(int j = 0; j < opc; j += 1)
|
||||
{
|
||||
switch(ops[j].type)
|
||||
{
|
||||
case OPTP_INT:
|
||||
fprintf(stderr, "%lld ", ops[j].as_int);
|
||||
break;
|
||||
|
||||
case OPTP_FLOAT:
|
||||
fprintf(stderr, "%f ", ops[j].as_float);
|
||||
break;
|
||||
|
||||
case OPTP_STRING:
|
||||
fprintf(stderr, "[%s] ", ops[j].as_string);
|
||||
break;
|
||||
|
||||
case OPTP_PROMISE:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
case OPTP_PROMISE:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
_Bool Executable_SetSource(Executable *exe, Source *src)
|
||||
@@ -232,46 +232,46 @@ _Bool Executable_Fetch(Executable *exe, int index, Opcode *opcode, Operand *ops,
|
||||
int i;
|
||||
|
||||
if(ops && opc)
|
||||
{
|
||||
int k = MIN(*opc, info->opcount);
|
||||
|
||||
for(i = 0; i < k; i += 1)
|
||||
{
|
||||
int k = MIN(*opc, info->opcount);
|
||||
OperandType type = info->optypes[i];
|
||||
assert(type != OPTP_PROMISE);
|
||||
|
||||
for(i = 0; i < k; i += 1)
|
||||
switch(type)
|
||||
{
|
||||
case OPTP_STRING:
|
||||
{
|
||||
OperandType type = info->optypes[i];
|
||||
assert(type != OPTP_PROMISE);
|
||||
int data_offset = instr->operands[i].as_int;
|
||||
|
||||
switch(type) {
|
||||
assert(data_offset < exe->headl);
|
||||
|
||||
case OPTP_STRING:
|
||||
{
|
||||
int data_offset = instr->operands[i].as_int;
|
||||
|
||||
assert(data_offset < exe->headl);
|
||||
|
||||
ops[i].type = OPTP_STRING;
|
||||
ops[i].as_string = exe->head + data_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPTP_INT:
|
||||
ops[i].type = OPTP_INT;
|
||||
ops[i].as_int = instr->operands[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_FLOAT:
|
||||
ops[i].type = OPTP_FLOAT;
|
||||
ops[i].as_int = instr->operands[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_PROMISE:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
ops[i].type = OPTP_STRING;
|
||||
ops[i].as_string = exe->head + data_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
*opc = MIN(*opc, info->opcount);
|
||||
case OPTP_INT:
|
||||
ops[i].type = OPTP_INT;
|
||||
ops[i].as_int = instr->operands[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_FLOAT:
|
||||
ops[i].type = OPTP_FLOAT;
|
||||
ops[i].as_int = instr->operands[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_PROMISE:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*opc = MIN(*opc, info->opcount);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -298,10 +298,10 @@ Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error)
|
||||
assert(exeb != NULL);
|
||||
|
||||
if(exeb->promc > 0)
|
||||
{
|
||||
Error_Report(error, 0, "There are still %d unfulfilled promises", exeb->promc);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "There are still %d unfulfilled promises", exeb->promc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable *exe;
|
||||
{
|
||||
@@ -313,10 +313,10 @@ Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error)
|
||||
void *temp = malloc(sizeof(Executable) + data_size + code_size);
|
||||
|
||||
if(temp == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
exe = temp;
|
||||
exe->headl = data_size;
|
||||
@@ -369,13 +369,13 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
|
||||
const InstrInfo *info = instr_table + opcode;
|
||||
|
||||
if(opc != info->opcount)
|
||||
{
|
||||
// ERROR: Too many operands were provided.
|
||||
Error_Report(error, 0,
|
||||
"Instruction %s expects %d operands, but %d were provided",
|
||||
info->name, info->opcount, opc);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
// ERROR: Too many operands were provided.
|
||||
Error_Report(error, 0,
|
||||
"Instruction %s expects %d operands, but %d were provided",
|
||||
info->name, info->opcount, opc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(opc <= MAX_OPS);
|
||||
|
||||
@@ -383,106 +383,104 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
|
||||
Instruction *instr = BucketList_Append2(exeb->code, NULL, sizeof(Instruction));
|
||||
|
||||
if(instr == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
instr->opcode = opcode;
|
||||
instr->offset = off;
|
||||
instr->length = len;
|
||||
|
||||
for(int i = 0; i < opc; i += 1)
|
||||
{
|
||||
// Check that the expected type and the provided one
|
||||
// match, or that the provided type is a promise with
|
||||
// the same size of the expected type.
|
||||
{
|
||||
// Check that the expected type and the provided one
|
||||
// match, or that the provided type is a promise with
|
||||
// the same size of the expected type.
|
||||
OperandType expected_type = info->optypes[i];
|
||||
OperandType provided_type = opv[i].type;
|
||||
|
||||
assert(expected_type != OPTP_PROMISE);
|
||||
|
||||
if(provided_type == OPTP_PROMISE)
|
||||
{
|
||||
OperandType expected_type = info->optypes[i];
|
||||
OperandType provided_type = opv[i].type;
|
||||
assert(opv[i].as_promise != NULL);
|
||||
|
||||
assert(expected_type != OPTP_PROMISE);
|
||||
|
||||
if(provided_type == OPTP_PROMISE)
|
||||
{
|
||||
assert(opv[i].as_promise != NULL);
|
||||
|
||||
if(expected_type == OPTP_STRING)
|
||||
{
|
||||
Error_Report(error, 0, "Promise values can't be provided as string operands");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Promise_Size(opv[i].as_promise) != operand_type_sizes[expected_type])
|
||||
{
|
||||
Error_Report(error, 0,
|
||||
"Provided promise has a value size of %d, "
|
||||
"but since %s %s was expected, the promise "
|
||||
"size must be %d",
|
||||
Promise_Size(opv[i].as_promise),
|
||||
operand_type_arts[expected_type],
|
||||
operand_type_names[expected_type],
|
||||
operand_type_sizes[expected_type]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(expected_type != provided_type)
|
||||
{
|
||||
// ERROR: Wrong operand type provided.
|
||||
Error_Report(error, 0,
|
||||
"Instruction %s expects %s %s as operand %d, but %s %s was provided instead",
|
||||
info->name,
|
||||
operand_type_arts[expected_type],
|
||||
operand_type_names[expected_type],
|
||||
i,
|
||||
operand_type_arts[provided_type],
|
||||
operand_type_names[provided_type]
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the copying of the operands.
|
||||
switch(opv[i].type)
|
||||
if(expected_type == OPTP_STRING)
|
||||
{
|
||||
case OPTP_STRING:
|
||||
|
||||
instr->operands[i].as_int = BucketList_Size(exeb->data);
|
||||
|
||||
if(!BucketList_Append(exeb->data, opv[i].as_string, strlen(opv[i].as_string)+1))
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTP_PROMISE:
|
||||
|
||||
assert(info->optypes[i] != OPTP_STRING);
|
||||
|
||||
// This must be incremented before subscribing
|
||||
// since the counter-decrementing callback may
|
||||
// be called immediately if the promise was
|
||||
// already fulfilled.
|
||||
exeb->promc += 1;
|
||||
|
||||
if(!Promise_Subscribe2(opv[i].as_promise, &instr->operands[i], exeb, promise_callback))
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTP_INT:
|
||||
instr->operands[i].as_int = opv[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_FLOAT:
|
||||
instr->operands[i].as_float = opv[i].as_float;
|
||||
break;
|
||||
|
||||
Error_Report(error, 0, "Promise values can't be provided as string operands");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Promise_Size(opv[i].as_promise) != operand_type_sizes[expected_type])
|
||||
{
|
||||
Error_Report(error, 0,
|
||||
"Provided promise has a value size of %d, "
|
||||
"but since %s %s was expected, the promise "
|
||||
"size must be %d",
|
||||
Promise_Size(opv[i].as_promise),
|
||||
operand_type_arts[expected_type],
|
||||
operand_type_names[expected_type],
|
||||
operand_type_sizes[expected_type]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(expected_type != provided_type)
|
||||
{
|
||||
// ERROR: Wrong operand type provided.
|
||||
Error_Report(error, 0,
|
||||
"Instruction %s expects %s %s as operand %d, but %s %s was provided instead",
|
||||
info->name,
|
||||
operand_type_arts[expected_type],
|
||||
operand_type_names[expected_type],
|
||||
i,
|
||||
operand_type_arts[provided_type],
|
||||
operand_type_names[provided_type]
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the copying of the operands.
|
||||
switch(opv[i].type)
|
||||
{
|
||||
case OPTP_STRING:
|
||||
|
||||
instr->operands[i].as_int = BucketList_Size(exeb->data);
|
||||
|
||||
if(!BucketList_Append(exeb->data, opv[i].as_string, strlen(opv[i].as_string)+1))
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTP_PROMISE:
|
||||
assert(info->optypes[i] != OPTP_STRING);
|
||||
|
||||
// This must be incremented before subscribing
|
||||
// since the counter-decrementing callback may
|
||||
// be called immediately if the promise was
|
||||
// already fulfilled.
|
||||
exeb->promc += 1;
|
||||
|
||||
if(!Promise_Subscribe2(opv[i].as_promise, &instr->operands[i], exeb, promise_callback))
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTP_INT:
|
||||
instr->operands[i].as_int = opv[i].as_int;
|
||||
break;
|
||||
|
||||
case OPTP_FLOAT:
|
||||
instr->operands[i].as_float = opv[i].as_float;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+556
-557
File diff suppressed because it is too large
Load Diff
+1123
-1144
File diff suppressed because it is too large
Load Diff
+138
-139
@@ -57,14 +57,14 @@ static void print_error(const char *type, Error *error)
|
||||
|
||||
#ifdef DEBUG
|
||||
if(error->file != NULL)
|
||||
{
|
||||
if(error->line > 0 && error->func != NULL)
|
||||
fprintf(stderr, " (Reported in %s:%d in %s)", error->file, error->line, error->func);
|
||||
else if(error->line > 0 && error->func == NULL)
|
||||
fprintf(stderr, " (Reported in %s:%d)", error->file, error->line);
|
||||
else if(error->line < 1 && error->func != NULL)
|
||||
fprintf(stderr, " (Reported in %s in %s)", error->file, error->func);
|
||||
}
|
||||
{
|
||||
if(error->line > 0 && error->func != NULL)
|
||||
fprintf(stderr, " (Reported in %s:%d in %s)", error->file, error->line, error->func);
|
||||
else if(error->line > 0 && error->func == NULL)
|
||||
fprintf(stderr, " (Reported in %s:%d)", error->file, error->line);
|
||||
else if(error->line < 1 && error->func != NULL)
|
||||
fprintf(stderr, " (Reported in %s in %s)", error->file, error->func);
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
@@ -78,10 +78,10 @@ static Executable *build(Source *src)
|
||||
BPAlloc *alloc = BPAlloc_Init(-1);
|
||||
|
||||
if(alloc == NULL)
|
||||
{
|
||||
fprintf(stderr, "Internal Error: Couldn't allocate bump-pointer allocator to hold the AST.\n");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
fprintf(stderr, "Internal Error: Couldn't allocate bump-pointer allocator to hold the AST.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
@@ -91,13 +91,13 @@ static Executable *build(Source *src)
|
||||
AST *ast = parse(src, alloc, &error);
|
||||
|
||||
if(ast == NULL)
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error("Parsing", &error);
|
||||
Error_Free(&error);
|
||||
BPAlloc_Free(alloc);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error("Parsing", &error);
|
||||
Error_Free(&error);
|
||||
BPAlloc_Free(alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
exe = compile(ast, alloc, &error);
|
||||
|
||||
@@ -106,12 +106,12 @@ static Executable *build(Source *src)
|
||||
BPAlloc_Free(alloc);
|
||||
|
||||
if(exe == NULL)
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error("Compilation", &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error("Compilation", &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return exe;
|
||||
}
|
||||
@@ -123,18 +123,18 @@ static _Bool interpret(Source *src)
|
||||
if(exe == NULL)
|
||||
return 0;
|
||||
|
||||
Runtime *runt = Runtime_New(-1, -1, NULL, NULL);
|
||||
Runtime *runt = Runtime_New(-1, 1024*1024, NULL, NULL);
|
||||
|
||||
if(runt == NULL)
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
Error_Report(&error, 1, "Couldn't initialize runtime");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
Executable_Free(exe);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
Error_Report(&error, 1, "Couldn't initialize runtime");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
Executable_Free(exe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We use a [RuntimeError] instead of a simple [Error]
|
||||
// because the [RuntimeError] makes a snapshot of the
|
||||
@@ -148,14 +148,14 @@ static _Bool interpret(Source *src)
|
||||
Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error);
|
||||
|
||||
if(bins == NULL)
|
||||
{
|
||||
assert(error.base.occurred == 1);
|
||||
print_error(NULL, (Error*) &error);
|
||||
RuntimeError_Free(&error);
|
||||
Executable_Free(exe);
|
||||
Runtime_Free(runt);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.base.occurred == 1);
|
||||
print_error(NULL, (Error*) &error);
|
||||
RuntimeError_Free(&error);
|
||||
Executable_Free(exe);
|
||||
Runtime_Free(runt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Runtime_SetBuiltins(runt, bins);
|
||||
|
||||
@@ -165,16 +165,16 @@ static _Bool interpret(Source *src)
|
||||
// now because it may be moved by the garbage collector.
|
||||
|
||||
if(o == NULL)
|
||||
{
|
||||
print_error("Runtime", (Error*) &error);
|
||||
{
|
||||
print_error("Runtime", (Error*) &error);
|
||||
|
||||
if(error.snapshot == NULL)
|
||||
fprintf(stderr, "No snapshot available.\n");
|
||||
else
|
||||
Snapshot_Print(error.snapshot, stderr);
|
||||
if(error.snapshot == NULL)
|
||||
fprintf(stderr, "No snapshot available.\n");
|
||||
else
|
||||
Snapshot_Print(error.snapshot, stderr);
|
||||
|
||||
RuntimeError_Free(&error);
|
||||
}
|
||||
RuntimeError_Free(&error);
|
||||
}
|
||||
|
||||
Runtime_Free(runt);
|
||||
Executable_Free(exe);
|
||||
@@ -201,12 +201,12 @@ static _Bool interpret_file(const char *file)
|
||||
Source *src = Source_FromFile(file, &error);
|
||||
|
||||
if(src == NULL)
|
||||
{
|
||||
assert(error.occurred == 1);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred == 1);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Bool r = interpret(src);
|
||||
|
||||
@@ -222,12 +222,12 @@ static _Bool interpret_code(const char *code)
|
||||
Source *src = Source_FromString(NULL, code, -1, &error);
|
||||
|
||||
if(src == NULL)
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Bool r = interpret(src);
|
||||
|
||||
@@ -243,12 +243,12 @@ static _Bool disassemble_file(const char *file)
|
||||
Source *src = Source_FromFile(file, &error);
|
||||
|
||||
if(src == NULL)
|
||||
{
|
||||
assert(error.occurred == 1);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred == 1);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Bool r = disassemble(src);
|
||||
|
||||
@@ -264,12 +264,12 @@ static _Bool disassemble_code(const char *code)
|
||||
Source *src = Source_FromString(NULL, code, -1, &error);
|
||||
|
||||
if(src == NULL)
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
assert(error.occurred);
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Bool r = disassemble(src);
|
||||
|
||||
@@ -282,82 +282,81 @@ int main(int argc, char **argv)
|
||||
assert(argc > 0);
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
// $ noja
|
||||
fprintf(stderr, "Error: Incorrect usage.\n\n");
|
||||
fprintf(stderr, usage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1], "run"))
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
// $ noja
|
||||
fprintf(stderr, "Error: Incorrect usage.\n\n");
|
||||
fprintf(stderr, usage);
|
||||
Error_Report(&error, 0, "Missing source file");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1], "run"))
|
||||
_Bool r;
|
||||
|
||||
if(!strcmp(argv[2], "inline"))
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source file");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_Bool r;
|
||||
|
||||
if(!strcmp(argv[2], "inline"))
|
||||
{
|
||||
if(argc == 3)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source string");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = interpret_code(argv[3]);
|
||||
}
|
||||
else
|
||||
r = interpret_file(argv[2]);
|
||||
return r ? 0 : -1;
|
||||
if(argc == 3)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source string");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
r = interpret_code(argv[3]);
|
||||
}
|
||||
else
|
||||
r = interpret_file(argv[2]);
|
||||
return r ? 0 : -1;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1], "dis"))
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
Error error;
|
||||
Error_Init(&error);
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source file");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_Bool r;
|
||||
|
||||
if(!strcmp(argv[2], "inline"))
|
||||
{
|
||||
if(argc == 3)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source string");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = disassemble_code(argv[3]);
|
||||
}
|
||||
else
|
||||
r = disassemble_file(argv[2]);
|
||||
return r ? 0 : -1;
|
||||
Error_Report(&error, 0, "Missing source file");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_Bool r;
|
||||
|
||||
if(!strcmp(argv[2], "inline"))
|
||||
{
|
||||
if(argc == 3)
|
||||
{
|
||||
Error_Report(&error, 0, "Missing source string");
|
||||
print_error(NULL, &error);
|
||||
Error_Free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = disassemble_code(argv[3]);
|
||||
}
|
||||
else
|
||||
r = disassemble_file(argv[2]);
|
||||
return r ? 0 : -1;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1], "help"))
|
||||
{
|
||||
fprintf(stdout, usage);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
fprintf(stdout, usage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Error: Incorrect usage.\n\n");
|
||||
fprintf(stderr, usage);
|
||||
|
||||
+156
-154
@@ -137,10 +137,10 @@ Heap *Heap_New(int size)
|
||||
heap->collecting = 0;
|
||||
|
||||
if(heap->body == NULL)
|
||||
{
|
||||
free(heap);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
free(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if USING_VALGRIND
|
||||
VALGRIND_CREATE_MEMPOOL(heap, 0, 0);
|
||||
@@ -160,23 +160,23 @@ void Heap_Free(Heap *heap)
|
||||
Error_Init(&error);
|
||||
|
||||
for(int i = 0; i < heap->pend_used; i += 1)
|
||||
{
|
||||
heap->pend[i].destructor(heap->pend[i].object, &error);
|
||||
if(error.occurred)
|
||||
{
|
||||
heap->pend[i].destructor(heap->pend[i].object, &error);
|
||||
if(error.occurred)
|
||||
{
|
||||
// Errors occurred! We can't do anything about
|
||||
// it now though.
|
||||
Error_Free(&error);
|
||||
Error_Init(&error);
|
||||
}
|
||||
// Errors occurred! We can't do anything about
|
||||
// it now though.
|
||||
Error_Free(&error);
|
||||
Error_Init(&error);
|
||||
}
|
||||
}
|
||||
|
||||
while(heap->oflow)
|
||||
{
|
||||
OflowAlloc *prev = heap->oflow->prev;
|
||||
free(heap->oflow);
|
||||
heap->oflow = prev;
|
||||
}
|
||||
{
|
||||
OflowAlloc *prev = heap->oflow->prev;
|
||||
free(heap->oflow);
|
||||
heap->oflow = prev;
|
||||
}
|
||||
|
||||
free(heap->pend);
|
||||
free(heap->body);
|
||||
@@ -208,42 +208,42 @@ void *Heap_Malloc(Heap *heap, TypeObject *type, Error *err)
|
||||
_Bool requires_destruct = type->free != NULL;
|
||||
|
||||
if(requires_destruct)
|
||||
{
|
||||
// This type of object requires
|
||||
// a destructor to be called.
|
||||
if(heap->pend == NULL)
|
||||
{
|
||||
// This type of object requires
|
||||
// a destructor to be called.
|
||||
int n = 8;
|
||||
|
||||
heap->pend = malloc(n * sizeof(PendingDestruct));
|
||||
|
||||
if(heap->pend == NULL)
|
||||
{
|
||||
int n = 8;
|
||||
{
|
||||
Error_Report(err, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->pend = malloc(n * sizeof(PendingDestruct));
|
||||
|
||||
if(heap->pend == NULL)
|
||||
{
|
||||
Error_Report(err, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->pend_used = 0;
|
||||
heap->pend_size = n;
|
||||
}
|
||||
else if(heap->pend_size == heap->pend_used)
|
||||
{
|
||||
int factor = 2;
|
||||
|
||||
void *new_pend = realloc(heap->pend, factor * heap->pend_size * sizeof(PendingDestruct));
|
||||
|
||||
if(new_pend == NULL)
|
||||
{
|
||||
Error_Report(err, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->pend = new_pend;
|
||||
heap->pend_size *= factor;
|
||||
}
|
||||
|
||||
assert(heap->pend_size > heap->pend_used);
|
||||
heap->pend_used = 0;
|
||||
heap->pend_size = n;
|
||||
}
|
||||
else if(heap->pend_size == heap->pend_used)
|
||||
{
|
||||
int factor = 2;
|
||||
|
||||
void *new_pend = realloc(heap->pend, factor * heap->pend_size * sizeof(PendingDestruct));
|
||||
|
||||
if(new_pend == NULL)
|
||||
{
|
||||
Error_Report(err, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->pend = new_pend;
|
||||
heap->pend_size *= factor;
|
||||
}
|
||||
|
||||
assert(heap->pend_size > heap->pend_used);
|
||||
}
|
||||
|
||||
int size = type->size;
|
||||
|
||||
@@ -290,23 +290,23 @@ void *Heap_RawMalloc(Heap *heap, int size, Error *err)
|
||||
padding = heap->used - padding;
|
||||
|
||||
if(heap->used + size > heap->size)
|
||||
{
|
||||
OflowAlloc *oflow = malloc(sizeof(OflowAlloc) + size);
|
||||
{
|
||||
OflowAlloc *oflow = malloc(sizeof(OflowAlloc) + size);
|
||||
|
||||
if(oflow == 0)
|
||||
return 0;
|
||||
if(oflow == 0)
|
||||
return 0;
|
||||
|
||||
oflow->prev = heap->oflow;
|
||||
heap->oflow = oflow;
|
||||
oflow->prev = heap->oflow;
|
||||
heap->oflow = oflow;
|
||||
|
||||
addr = oflow->body;
|
||||
}
|
||||
addr = oflow->body;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(heap->used + size <= heap->size);
|
||||
addr = heap->body + heap->used;
|
||||
heap->used += size;
|
||||
}
|
||||
{
|
||||
assert(heap->used + size <= heap->size);
|
||||
addr = heap->body + heap->used;
|
||||
heap->used += size;
|
||||
}
|
||||
|
||||
heap->total += size + padding;
|
||||
|
||||
@@ -326,10 +326,10 @@ _Bool Heap_StartCollection(Heap *heap, Error *error)
|
||||
void *new_body = malloc(heap->size);
|
||||
|
||||
if(new_body == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
heap->old_body = heap->body;
|
||||
heap->old_used = heap->used;
|
||||
@@ -351,57 +351,57 @@ _Bool Heap_StopCollection(Heap *heap)
|
||||
assert(heap->collecting == 1);
|
||||
|
||||
if(heap->collection_failed)
|
||||
{
|
||||
free(heap->old_body);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
free(heap->old_body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call destructors here */
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while(i < heap->pend_used)
|
||||
{
|
||||
Object *obj = heap->pend[i].object;
|
||||
|
||||
if(obj->flags & Object_MOVED)
|
||||
{
|
||||
Object *obj = heap->pend[i].object;
|
||||
|
||||
if(obj->flags & Object_MOVED)
|
||||
{
|
||||
heap->pend[i].object = ((MovedObject*) heap->pend[i].object)->new_location;
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to call the destructor.
|
||||
|
||||
heap->pend[i].destructor(obj, heap->error);
|
||||
|
||||
if(heap->error->occurred)
|
||||
return 0; // There will be leaks.
|
||||
|
||||
heap->pend[i] = heap->pend[heap->pend_used-1];
|
||||
heap->pend_used -= 1;
|
||||
}
|
||||
heap->pend[i].object = ((MovedObject*) heap->pend[i].object)->new_location;
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to call the destructor.
|
||||
|
||||
heap->pend[i].destructor(obj, heap->error);
|
||||
|
||||
if(heap->error->occurred)
|
||||
return 0; // There will be leaks.
|
||||
|
||||
heap->pend[i] = heap->pend[heap->pend_used-1];
|
||||
heap->pend_used -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(heap->pend_size / 2 > heap->pend_used)
|
||||
{
|
||||
// Downsize
|
||||
void *temp = realloc(heap->pend, heap->pend_size / 2 * sizeof(PendingDestruct));
|
||||
{
|
||||
// Downsize
|
||||
void *temp = realloc(heap->pend, heap->pend_size / 2 * sizeof(PendingDestruct));
|
||||
|
||||
if(temp != NULL)
|
||||
{
|
||||
heap->pend = temp;
|
||||
heap->pend_size /= 2;
|
||||
}
|
||||
if(temp != NULL)
|
||||
{
|
||||
heap->pend = temp;
|
||||
heap->pend_size /= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(heap->old_oflow)
|
||||
{
|
||||
OflowAlloc *prev = heap->old_oflow->prev;
|
||||
free(heap->old_oflow);
|
||||
heap->old_oflow = prev;
|
||||
}
|
||||
{
|
||||
OflowAlloc *prev = heap->old_oflow->prev;
|
||||
free(heap->old_oflow);
|
||||
heap->old_oflow = prev;
|
||||
}
|
||||
|
||||
free(heap->old_body);
|
||||
|
||||
@@ -425,10 +425,10 @@ void Heap_CollectExtension(void **referer, unsigned int size, void *userp)
|
||||
void *new_location = Heap_RawMalloc(heap, size, heap->error);
|
||||
|
||||
if(new_location == NULL)
|
||||
{
|
||||
heap->collection_failed = 1;
|
||||
return;
|
||||
}
|
||||
{
|
||||
heap->collection_failed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(new_location, old_location, size);
|
||||
|
||||
@@ -453,62 +453,64 @@ void Heap_CollectReference(Object **referer, void *userp)
|
||||
*referer = ((MovedObject*) old_location)->new_location;
|
||||
|
||||
else
|
||||
{
|
||||
Object *new_location;
|
||||
|
||||
// This object wasn't moved to
|
||||
// the new heap yet.
|
||||
|
||||
if(old_location->flags & Object_STATIC)
|
||||
|
||||
// The object doesn't need to be moved
|
||||
// since it was statically allocated.
|
||||
new_location = old_location;
|
||||
else
|
||||
{
|
||||
Object *new_location;
|
||||
// Get some information.
|
||||
TypeObject *type = old_location->type;
|
||||
int size = type->size;
|
||||
|
||||
// This object wasn't moved to
|
||||
// the new heap yet.
|
||||
// Copy the object to a new location.
|
||||
{
|
||||
new_location = Heap_RawMalloc(heap, size, heap->error);
|
||||
|
||||
if(old_location->flags & Object_STATIC)
|
||||
|
||||
// The object doesn't need to be moved
|
||||
// since it was statically allocated.
|
||||
new_location = old_location;
|
||||
else
|
||||
if(new_location == NULL)
|
||||
{
|
||||
// Get some information.
|
||||
TypeObject *type = old_location->type;
|
||||
int size = type->size;
|
||||
|
||||
// Copy the object to a new location.
|
||||
{
|
||||
new_location = Heap_RawMalloc(heap, size, heap->error);
|
||||
|
||||
if(new_location == NULL)
|
||||
{
|
||||
heap->collection_failed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(new_location, old_location, size);
|
||||
}
|
||||
|
||||
// Set the old location as moved and
|
||||
// leave the reference to the new
|
||||
// location.
|
||||
{
|
||||
old_location->flags |= Object_MOVED;
|
||||
|
||||
assert((int) sizeof(MovedObject) <= size);
|
||||
((MovedObject*) old_location)->new_location = new_location;
|
||||
}
|
||||
|
||||
heap->movedcount += 1;
|
||||
heap->collection_failed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect the reference to the type.
|
||||
if((Object*) new_location->type != new_location)
|
||||
Heap_CollectReference((Object**) &new_location->type, heap);
|
||||
memcpy(new_location, old_location, size);
|
||||
}
|
||||
|
||||
// Collect all of the references to
|
||||
// extensions allocate using the GC'd
|
||||
// heap.
|
||||
Object_WalkExtensions(new_location, Heap_CollectExtension, heap);
|
||||
// Set the old location as moved and
|
||||
// leave the reference to the new
|
||||
// location.
|
||||
{
|
||||
old_location->flags |= Object_MOVED;
|
||||
|
||||
// Now collect all of the children.
|
||||
Object_WalkReferences(new_location, Heap_CollectReference, heap);
|
||||
assert((int) sizeof(MovedObject) <= size);
|
||||
((MovedObject*) old_location)->new_location = new_location;
|
||||
}
|
||||
|
||||
// Update the referer
|
||||
*referer = new_location;
|
||||
heap->movedcount += 1;
|
||||
}
|
||||
|
||||
// Collect the reference to the type.
|
||||
if((Object*) new_location->type != new_location)
|
||||
Heap_CollectReference((Object**) &new_location->type, heap);
|
||||
|
||||
// Collect all of the references to
|
||||
// extensions allocate using the GC'd
|
||||
// heap.
|
||||
Object_WalkExtensions(new_location,
|
||||
Heap_CollectExtension, heap);
|
||||
|
||||
// Now collect all of the children.
|
||||
Object_WalkReferences(new_location,
|
||||
Heap_CollectReference, heap);
|
||||
|
||||
// Update the referer
|
||||
*referer = new_location;
|
||||
}
|
||||
}
|
||||
+148
-148
@@ -102,22 +102,22 @@ Object *Object_NewBuffer(int size, Heap *heap, Error *error)
|
||||
unsigned char *body;
|
||||
|
||||
if(size > THRESHOLD)
|
||||
{
|
||||
body = malloc(sizeof(unsigned char) * size);
|
||||
{
|
||||
body = malloc(sizeof(unsigned char) * size);
|
||||
|
||||
if(body == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
if(body == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error);
|
||||
{
|
||||
body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error);
|
||||
|
||||
if(body == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if(body == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj->size = size;
|
||||
obj->body = body;
|
||||
@@ -141,112 +141,112 @@ static _Bool buffer_free(Object *self, Error *error)
|
||||
Object *Object_SliceBuffer(Object *buffer, int offset, int length, Heap *heap, Error *error)
|
||||
{
|
||||
if(buffer->type != &t_buffer && buffer->type != &t_buffer_slice)
|
||||
{
|
||||
Error_Report(error, 0, "Not a buffer or a buffer slice");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Not a buffer or a buffer slice");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BufferSliceObject *slice;
|
||||
|
||||
if(buffer->type == &t_buffer)
|
||||
{
|
||||
BufferObject *original = (BufferObject*) buffer;
|
||||
|
||||
if(offset == 0 && length == original->size)
|
||||
return buffer;
|
||||
|
||||
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
|
||||
|
||||
if(slice == NULL)
|
||||
return NULL;
|
||||
|
||||
if(offset < 0 || offset >= original->size)
|
||||
{
|
||||
BufferObject *original = (BufferObject*) buffer;
|
||||
|
||||
if(offset == 0 && length == original->size)
|
||||
return buffer;
|
||||
|
||||
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
|
||||
|
||||
if(slice == NULL)
|
||||
return NULL;
|
||||
|
||||
if(offset < 0 || offset >= original->size)
|
||||
{
|
||||
Error_Report(error, 0, "offset out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(length < 0 || length >= original->size)
|
||||
{
|
||||
Error_Report(error, 0, "length out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(offset + length > original->size)
|
||||
{
|
||||
Error_Report(error, 0, "slice out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slice->sliced = original;
|
||||
slice->offset = offset;
|
||||
slice->length = length;
|
||||
Error_Report(error, 0, "offset out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(length < 0 || length >= original->size)
|
||||
{
|
||||
Error_Report(error, 0, "length out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(offset + length > original->size)
|
||||
{
|
||||
Error_Report(error, 0, "slice out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slice->sliced = original;
|
||||
slice->offset = offset;
|
||||
slice->length = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(buffer->type == &t_buffer_slice);
|
||||
|
||||
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
|
||||
|
||||
if(slice == NULL)
|
||||
return NULL;
|
||||
|
||||
BufferSliceObject *original = (BufferSliceObject*) buffer;
|
||||
|
||||
if(offset < 0 || offset >= original->length)
|
||||
{
|
||||
assert(buffer->type == &t_buffer_slice);
|
||||
|
||||
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
|
||||
|
||||
if(slice == NULL)
|
||||
return NULL;
|
||||
|
||||
BufferSliceObject *original = (BufferSliceObject*) buffer;
|
||||
|
||||
if(offset < 0 || offset >= original->length)
|
||||
{
|
||||
Error_Report(error, 0, "offset out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(length < 0 || length >= original->length)
|
||||
{
|
||||
Error_Report(error, 0, "length out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(offset + length > original->length)
|
||||
{
|
||||
Error_Report(error, 0, "slice out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slice->sliced = original->sliced;
|
||||
slice->offset = original->offset + offset;
|
||||
slice->length = length;
|
||||
Error_Report(error, 0, "offset out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(length < 0 || length >= original->length)
|
||||
{
|
||||
Error_Report(error, 0, "length out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(offset + length > original->length)
|
||||
{
|
||||
Error_Report(error, 0, "slice out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slice->sliced = original->sliced;
|
||||
slice->offset = original->offset + offset;
|
||||
slice->length = length;
|
||||
}
|
||||
|
||||
return (Object*) slice;
|
||||
}
|
||||
|
||||
void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error)
|
||||
{
|
||||
if(obj->type != &t_buffer && obj->type != &t_buffer_slice)
|
||||
{
|
||||
Error_Report(error, 0, "Not a buffer or a buffer slice");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Not a buffer or a buffer slice");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(obj->type == &t_buffer)
|
||||
{
|
||||
BufferObject *buffer = (BufferObject*) obj;
|
||||
{
|
||||
BufferObject *buffer = (BufferObject*) obj;
|
||||
|
||||
if(size)
|
||||
*size = buffer->size;
|
||||
if(size)
|
||||
*size = buffer->size;
|
||||
|
||||
return buffer->body;
|
||||
}
|
||||
return buffer->body;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(obj->type == &t_buffer_slice);
|
||||
{
|
||||
assert(obj->type == &t_buffer_slice);
|
||||
|
||||
BufferSliceObject *slice = (BufferSliceObject*) obj;
|
||||
BufferSliceObject *slice = (BufferSliceObject*) obj;
|
||||
|
||||
if(size)
|
||||
*size = slice->length;
|
||||
if(size)
|
||||
*size = slice->length;
|
||||
|
||||
return slice->sliced->body + slice->offset;
|
||||
}
|
||||
return slice->sliced->body + slice->offset;
|
||||
}
|
||||
}
|
||||
|
||||
static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
@@ -258,10 +258,10 @@ static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error
|
||||
assert(error != NULL);
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
@@ -269,10 +269,10 @@ static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error
|
||||
BufferObject *buffer = (BufferObject*) self;
|
||||
|
||||
if(idx < 0 || idx >= buffer->size)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char byte = buffer->body[idx];
|
||||
|
||||
@@ -288,10 +288,10 @@ static Object *slice_select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
assert(error != NULL);
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
@@ -299,10 +299,10 @@ static Object *slice_select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
BufferSliceObject *slice = (BufferSliceObject*) self;
|
||||
|
||||
if(idx < 0 || idx >= slice->length)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char byte = slice->sliced->body[slice->offset + idx];
|
||||
|
||||
@@ -321,27 +321,27 @@ static _Bool buffer_insert(Object *self, Object *key, Object *val, Heap *heap, E
|
||||
BufferObject *buffer = (BufferObject*) self;
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
|
||||
if(idx < 0 || idx >= buffer->size)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long long int qword = Object_ToInt(val, error);
|
||||
|
||||
if(qword > 255 || qword < 0)
|
||||
{
|
||||
Error_Report(error, 0, "Not in range [0, 255]");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Not in range [0, 255]");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char byte = qword & 0xff;
|
||||
|
||||
@@ -364,27 +364,27 @@ static _Bool slice_insert(Object *self, Object *key, Object *val, Heap *heap, Er
|
||||
BufferSliceObject *slice = (BufferSliceObject*) self;
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
|
||||
if(idx < 0 || idx >= slice->length)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long long int qword = Object_ToInt(val, error);
|
||||
|
||||
if(qword > 255 || qword < 0)
|
||||
{
|
||||
Error_Report(error, 0, "Not in range [0, 255]");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Not in range [0, 255]");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char byte = qword & 0xff;
|
||||
|
||||
@@ -414,26 +414,26 @@ static void print_bytes(FILE *fp, unsigned char *addr, int size)
|
||||
fprintf(fp, "[");
|
||||
|
||||
for(int i = 0; i < size; i += 1)
|
||||
{
|
||||
unsigned char byte, low, high;
|
||||
{
|
||||
unsigned char byte, low, high;
|
||||
|
||||
byte = addr[i];
|
||||
low = byte & 0xf;
|
||||
high = byte >> 4;
|
||||
byte = addr[i];
|
||||
low = byte & 0xf;
|
||||
high = byte >> 4;
|
||||
|
||||
assert(low < 16);
|
||||
assert(high < 16);
|
||||
assert(low < 16);
|
||||
assert(high < 16);
|
||||
|
||||
char c1, c2;
|
||||
char c1, c2;
|
||||
|
||||
c1 = low < 10 ? low + '0' : low - 10 + 'A';
|
||||
c2 = high < 10 ? high + '0' : high - 10 + 'A';
|
||||
c1 = low < 10 ? low + '0' : low - 10 + 'A';
|
||||
c2 = high < 10 ? high + '0' : high - 10 + 'A';
|
||||
|
||||
fprintf(fp, "%c%c", c2, c1);
|
||||
fprintf(fp, "%c%c", c2, c1);
|
||||
|
||||
if(i+1 < size)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
if(i+1 < size)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
fprintf(fp, "]");
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -58,10 +58,10 @@ Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *er
|
||||
return NULL;
|
||||
|
||||
if(parent != NULL && parent->type != &t_closure)
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a closure");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a closure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj->prev = (ClosureObject*) parent;
|
||||
obj->vars = new_map;
|
||||
@@ -76,14 +76,14 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err)
|
||||
Object *selected = NULL;
|
||||
|
||||
while(closure != NULL && selected == NULL)
|
||||
{
|
||||
selected = Object_Select(closure->vars, key, heap, err);
|
||||
{
|
||||
selected = Object_Select(closure->vars, key, heap, err);
|
||||
|
||||
if(err->occurred)
|
||||
return NULL;
|
||||
if(err->occurred)
|
||||
return NULL;
|
||||
|
||||
closure = closure->prev;
|
||||
}
|
||||
closure = closure->prev;
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
+4
-4
@@ -64,10 +64,10 @@ Object *Object_FromDIR(DIR *handle, Heap *heap, Error *error)
|
||||
DIR *Object_ToDIR(Object *obj, Error *error)
|
||||
{
|
||||
if(!Object_IsDir(obj))
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a directory");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a directory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((DirObject*) obj)->dir;
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ _Bool Object_IsFile(Object *obj)
|
||||
FILE *Object_ToStream(Object *obj, Error *error)
|
||||
{
|
||||
if(!Object_IsFile(obj))
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a file");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Object is not a file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((FileObject*) obj)->fp;
|
||||
}
|
||||
|
||||
+35
-35
@@ -89,10 +89,10 @@ static Object *copy(Object *self, Heap *heap, Error *err)
|
||||
if(ls2 == NULL) return NULL;
|
||||
|
||||
for(int i = 0; i < ls->count; i += 1)
|
||||
{
|
||||
ls2->vals[i] = Object_Copy(ls->vals[i], heap, err);
|
||||
if(err->occurred) return NULL;
|
||||
}
|
||||
{
|
||||
ls2->vals[i] = Object_Copy(ls->vals[i], heap, err);
|
||||
if(err->occurred) return NULL;
|
||||
}
|
||||
|
||||
ls2->count = ls->count;
|
||||
|
||||
@@ -168,10 +168,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
assert(error != NULL);
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
@@ -179,10 +179,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
ListObject *list = (ListObject*) self;
|
||||
|
||||
if(idx < 0 || idx >= list->count)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->vals[idx];
|
||||
}
|
||||
@@ -223,33 +223,33 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e
|
||||
ListObject *list = (ListObject*) self;
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
|
||||
if(idx < 0 || idx > list->count)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(idx == list->count)
|
||||
{
|
||||
if(list->count == list->capacity)
|
||||
if(!grow(list, heap, error))
|
||||
return 0;
|
||||
{
|
||||
if(list->count == list->capacity)
|
||||
if(!grow(list, heap, error))
|
||||
return 0;
|
||||
|
||||
list->vals[list->count] = val;
|
||||
list->count += 1;
|
||||
}
|
||||
list->vals[list->count] = val;
|
||||
list->count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->vals[idx] = val;
|
||||
}
|
||||
{
|
||||
list->vals[idx] = val;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -267,11 +267,11 @@ static void print(Object *self, FILE *fp)
|
||||
|
||||
fprintf(fp, "[");
|
||||
for(int i = 0; i < list->count; i += 1)
|
||||
{
|
||||
Object_Print(list->vals[i], fp);
|
||||
{
|
||||
Object_Print(list->vals[i], fp);
|
||||
|
||||
if(i+1 < list->count)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
if(i+1 < list->count)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
fprintf(fp, "]");
|
||||
}
|
||||
+115
-115
@@ -75,22 +75,22 @@ static Object *copy(Object *self, Heap *heap, Error *err)
|
||||
if(m2 == NULL) return NULL;
|
||||
|
||||
for(int i = 0; i < m1->count; i += 1)
|
||||
{
|
||||
Object *key, *key_cpy;
|
||||
Object *val, *val_cpy;
|
||||
{
|
||||
Object *key, *key_cpy;
|
||||
Object *val, *val_cpy;
|
||||
|
||||
key = m1->keys[i];
|
||||
val = m1->vals[i];
|
||||
key = m1->keys[i];
|
||||
val = m1->vals[i];
|
||||
|
||||
key_cpy = Object_Copy(key, heap, err);
|
||||
if(key_cpy == NULL) return NULL;
|
||||
key_cpy = Object_Copy(key, heap, err);
|
||||
if(key_cpy == NULL) return NULL;
|
||||
|
||||
val_cpy = Object_Copy(val, heap, err);
|
||||
if(val_cpy == NULL) return NULL;
|
||||
val_cpy = Object_Copy(val, heap, err);
|
||||
if(val_cpy == NULL) return NULL;
|
||||
|
||||
if(!Object_Insert(m2, key_cpy, val_cpy, heap, err))
|
||||
return NULL;
|
||||
}
|
||||
if(!Object_Insert(m2, key_cpy, val_cpy, heap, err))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (Object*) m2;
|
||||
}
|
||||
@@ -103,8 +103,8 @@ static int hash(Object *self)
|
||||
// The hash of the map is the sum of the
|
||||
// hashes of each key and each item.
|
||||
for(int i = 0; i < m->count; i += 1)
|
||||
h += Object_Hash(m->keys[i])
|
||||
+ Object_Hash(m->vals[i]);
|
||||
h += Object_Hash(m->keys[i])
|
||||
+ Object_Hash(m->vals[i]);
|
||||
return h;
|
||||
}
|
||||
|
||||
@@ -151,10 +151,10 @@ static void walk(Object *self, void (*callback)(Object **referer, void *userp),
|
||||
MapObject *map = (MapObject*) self;
|
||||
|
||||
for(int i = 0; i < map->count; i += 1)
|
||||
{
|
||||
callback(&map->keys[i], userp);
|
||||
callback(&map->vals[i], userp);
|
||||
}
|
||||
{
|
||||
callback(&map->keys[i], userp);
|
||||
callback(&map->vals[i], userp);
|
||||
}
|
||||
}
|
||||
|
||||
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
|
||||
@@ -187,36 +187,36 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
int i = hash & mask;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int k = map->mapper[i];
|
||||
|
||||
if(k == -1)
|
||||
{
|
||||
int k = map->mapper[i];
|
||||
|
||||
if(k == -1)
|
||||
{
|
||||
// Empty slot.
|
||||
// This key is not present.
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found an item.
|
||||
// Is it the right one?
|
||||
|
||||
assert(k >= 0);
|
||||
|
||||
if(Object_Compare(key, map->keys[k], error))
|
||||
// Found it!
|
||||
return map->vals[k];
|
||||
|
||||
if(error->occurred)
|
||||
// Key doesn't implement compare.
|
||||
return 0;
|
||||
|
||||
// Not the one we wanted.
|
||||
}
|
||||
|
||||
pert >>= 5;
|
||||
i = (i * 5 + pert + 1) & mask;
|
||||
// Empty slot.
|
||||
// This key is not present.
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found an item.
|
||||
// Is it the right one?
|
||||
|
||||
assert(k >= 0);
|
||||
|
||||
if(Object_Compare(key, map->keys[k], error))
|
||||
// Found it!
|
||||
return map->vals[k];
|
||||
|
||||
if(error->occurred)
|
||||
// Key doesn't implement compare.
|
||||
return 0;
|
||||
|
||||
// Not the one we wanted.
|
||||
}
|
||||
|
||||
pert >>= 5;
|
||||
i = (i * 5 + pert + 1) & mask;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
return NULL;
|
||||
@@ -237,42 +237,42 @@ static _Bool grow(MapObject *map, Heap *heap, Error *error)
|
||||
return 0;
|
||||
|
||||
for(int i = 0; i < map->count; i += 1)
|
||||
{
|
||||
keys[i] = map->keys[i];
|
||||
vals[i] = map->vals[i];
|
||||
}
|
||||
{
|
||||
keys[i] = map->keys[i];
|
||||
vals[i] = map->vals[i];
|
||||
}
|
||||
|
||||
for(int i = 0; i < new_mapper_size; i += 1)
|
||||
mapper[i] = -1;
|
||||
|
||||
// Rehash everything.
|
||||
for(int i = 0; i < map->count; i += 1)
|
||||
{
|
||||
// This won't trigger an error because the key
|
||||
// surely has a hash method since we already
|
||||
// hashed it once.
|
||||
int hash = Object_Hash(keys[i]);
|
||||
|
||||
int mask = new_mapper_size - 1;
|
||||
int pert = hash;
|
||||
|
||||
int j = hash & mask;
|
||||
|
||||
while(1)
|
||||
{
|
||||
// This won't trigger an error because the key
|
||||
// surely has a hash method since we already
|
||||
// hashed it once.
|
||||
int hash = Object_Hash(keys[i]);
|
||||
if(mapper[j] == -1)
|
||||
{
|
||||
// No collision.
|
||||
// Insert here.
|
||||
mapper[j] = i;
|
||||
break;
|
||||
}
|
||||
|
||||
int mask = new_mapper_size - 1;
|
||||
int pert = hash;
|
||||
|
||||
int j = hash & mask;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(mapper[j] == -1)
|
||||
{
|
||||
// No collision.
|
||||
// Insert here.
|
||||
mapper[j] = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Collided. Find a new place.
|
||||
pert >>= 5;
|
||||
j = (j * 5 + pert + 1) & mask;
|
||||
}
|
||||
// Collided. Find a new place.
|
||||
pert >>= 5;
|
||||
j = (j * 5 + pert + 1) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
// Done.
|
||||
map->mapper = mapper;
|
||||
@@ -304,45 +304,45 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e
|
||||
int i = hash & mask;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int k = map->mapper[i];
|
||||
|
||||
if(k == -1)
|
||||
{
|
||||
int k = map->mapper[i];
|
||||
// Empty slot. We can insert it here.
|
||||
Object *key_copy = Object_Copy(key, heap, error);
|
||||
|
||||
if(k == -1)
|
||||
{
|
||||
// Empty slot. We can insert it here.
|
||||
Object *key_copy = Object_Copy(key, heap, error);
|
||||
if(key_copy == NULL)
|
||||
return NULL;
|
||||
|
||||
if(key_copy == NULL)
|
||||
return NULL;
|
||||
|
||||
map->mapper[i] = map->count;
|
||||
map->keys[map->count] = key_copy;
|
||||
map->vals[map->count] = val;
|
||||
map->count += 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(k >= 0);
|
||||
|
||||
if(Object_Compare(key, map->keys[k], error))
|
||||
{
|
||||
// Already inserted.
|
||||
// Overwrite the value.
|
||||
map->vals[k] = val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(error->occurred)
|
||||
// Key doesn't implement compare.
|
||||
return 0;
|
||||
|
||||
// Collision.
|
||||
}
|
||||
|
||||
pert >>= 5;
|
||||
i = (i * 5 + pert + 1) & mask;
|
||||
map->mapper[i] = map->count;
|
||||
map->keys[map->count] = key_copy;
|
||||
map->vals[map->count] = val;
|
||||
map->count += 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(k >= 0);
|
||||
|
||||
if(Object_Compare(key, map->keys[k], error))
|
||||
{
|
||||
// Already inserted.
|
||||
// Overwrite the value.
|
||||
map->vals[k] = val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(error->occurred)
|
||||
// Key doesn't implement compare.
|
||||
return 0;
|
||||
|
||||
// Collision.
|
||||
}
|
||||
|
||||
pert >>= 5;
|
||||
i = (i * 5 + pert + 1) & mask;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
return 0;
|
||||
@@ -361,13 +361,13 @@ static void print(Object *self, FILE *fp)
|
||||
|
||||
fprintf(fp, "{");
|
||||
for(int i = 0; i < map->count; i += 1)
|
||||
{
|
||||
Object_Print(map->keys[i], fp);
|
||||
fprintf(fp, ": ");
|
||||
Object_Print(map->vals[i], fp);
|
||||
{
|
||||
Object_Print(map->keys[i], fp);
|
||||
fprintf(fp, ": ");
|
||||
Object_Print(map->vals[i], fp);
|
||||
|
||||
if(i+1 < map->count)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
if(i+1 < map->count)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
fprintf(fp, "}");
|
||||
}
|
||||
+21
-18
@@ -68,6 +68,9 @@ static TypeObject t_string = {
|
||||
|
||||
static int char_index_to_offset(StringObject *str, int idx)
|
||||
{
|
||||
if(str->count == str->bytes)
|
||||
return idx;
|
||||
|
||||
// Iterate over a string to find the first byte of
|
||||
// the utf-8 character number [idx].
|
||||
|
||||
@@ -75,13 +78,13 @@ static int char_index_to_offset(StringObject *str, int idx)
|
||||
last_code_len = 0;
|
||||
|
||||
while(idx > 0)
|
||||
{
|
||||
last_code_len = utf8_sequence_to_utf32_codepoint(str->body + scanned_bytes, str->bytes - scanned_bytes, NULL);
|
||||
scanned_bytes += last_code_len;
|
||||
idx -= 1;
|
||||
{
|
||||
last_code_len = utf8_sequence_to_utf32_codepoint(str->body + scanned_bytes, str->bytes - scanned_bytes, NULL);
|
||||
scanned_bytes += last_code_len;
|
||||
idx -= 1;
|
||||
|
||||
assert(scanned_bytes <= str->bytes);
|
||||
}
|
||||
assert(scanned_bytes <= str->bytes);
|
||||
}
|
||||
|
||||
assert(idx == 0);
|
||||
return scanned_bytes;
|
||||
@@ -93,10 +96,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
assert(key != NULL && heap != NULL && error != NULL);
|
||||
|
||||
if(!Object_IsInt(key))
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Non integer key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = Object_ToInt(key, error);
|
||||
assert(error->occurred == 0);
|
||||
@@ -104,10 +107,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
StringObject *str = (StringObject*) self;
|
||||
|
||||
if(idx < 0 || idx >= str->count)
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Out of range index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int byteoffset = char_index_to_offset(str, idx);
|
||||
int codelength = utf8_sequence_to_utf32_codepoint(str->body + byteoffset, str->bytes - byteoffset, NULL);
|
||||
@@ -143,10 +146,10 @@ Object *Object_FromString(const char *str, int len, Heap *heap, Error *error)
|
||||
int count = utf8_strlen(str, len);
|
||||
|
||||
if(count < 0)
|
||||
{
|
||||
Error_Report(error, 0, "Invalid UTF-8 sequence");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Invalid UTF-8 sequence");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringObject *strobj = Heap_Malloc(heap, &t_string, error);
|
||||
|
||||
|
||||
+72
-72
@@ -86,10 +86,10 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->deepsize == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return type->deepsize(obj);
|
||||
}
|
||||
@@ -112,10 +112,10 @@ Object *Object_Copy(Object *obj, Heap *heap, Error *err)
|
||||
assert(type != NULL);
|
||||
|
||||
if(type->copy == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->copy(obj, heap, err);
|
||||
}
|
||||
@@ -129,10 +129,10 @@ Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, E
|
||||
assert(type);
|
||||
|
||||
if(type->call == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->call(obj, argv, argc, heap, err);
|
||||
}
|
||||
@@ -160,10 +160,10 @@ Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->select == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->select(coll, key, heap, err);
|
||||
}
|
||||
@@ -178,10 +178,10 @@ Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->delete == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->delete(coll, key, heap, err);
|
||||
}
|
||||
@@ -196,10 +196,10 @@ _Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *e
|
||||
assert(type);
|
||||
|
||||
if(type->insert == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return type->insert(coll, key, val, heap, err);
|
||||
}
|
||||
@@ -213,10 +213,10 @@ int Object_Count(Object *coll, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->count == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return type->count(coll);
|
||||
}
|
||||
@@ -230,10 +230,10 @@ Object *Object_Next(Object *iter, Heap *heap, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->next == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->next(iter, heap, err);
|
||||
}
|
||||
@@ -247,10 +247,10 @@ Object *Object_Prev(Object *iter, Heap *heap, Error *err)
|
||||
assert(type);
|
||||
|
||||
if(type->prev == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->prev(iter, heap, err);
|
||||
}
|
||||
@@ -289,19 +289,19 @@ long long int Object_ToInt(Object *obj, Error *err)
|
||||
assert(obj);
|
||||
|
||||
if(!Object_IsInt(obj))
|
||||
{
|
||||
Error_Report(err, 0, "Object is not an integer");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object is not an integer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TypeObject *type = Object_GetType(obj);
|
||||
assert(type);
|
||||
|
||||
if(type->to_int == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return type->to_int(obj, err);
|
||||
}
|
||||
@@ -312,19 +312,19 @@ _Bool Object_ToBool(Object *obj, Error *err)
|
||||
assert(obj);
|
||||
|
||||
if(!Object_IsBool(obj))
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a boolean");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a boolean");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TypeObject *type = Object_GetType(obj);
|
||||
assert(type);
|
||||
|
||||
if(type->to_bool == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return type->to_bool(obj, err);
|
||||
}
|
||||
@@ -335,19 +335,19 @@ double Object_ToFloat(Object *obj, Error *err)
|
||||
assert(obj);
|
||||
|
||||
if(!Object_IsFloat(obj))
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a floating");
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a floating");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TypeObject *type = Object_GetType(obj);
|
||||
assert(type);
|
||||
|
||||
if(type->to_float == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return type->to_float(obj, err);
|
||||
}
|
||||
@@ -358,19 +358,19 @@ const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err)
|
||||
assert(obj != NULL);
|
||||
|
||||
if(!Object_IsString(obj))
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a string");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object is not a string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const TypeObject *type = Object_GetType(obj);
|
||||
assert(type);
|
||||
|
||||
if(type->to_string == NULL)
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return type->to_string(obj, size, heap, err);
|
||||
}
|
||||
@@ -385,10 +385,10 @@ _Bool Object_Compare(Object *obj1, Object *obj2, Error *error)
|
||||
return 0;
|
||||
|
||||
if(obj1->type->op_eql == NULL)
|
||||
{
|
||||
Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj1), __func__);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj1), __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return obj1->type->op_eql(obj1, obj2);
|
||||
}
|
||||
|
||||
+32
-34
@@ -59,9 +59,7 @@ static void walk(Object *self, void (*callback)(Object **referer, void *userp),
|
||||
|
||||
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error)
|
||||
{
|
||||
assert(self != NULL);
|
||||
assert(heap != NULL);
|
||||
assert(error != NULL);
|
||||
assert(self != NULL && heap != NULL && error != NULL);
|
||||
|
||||
FunctionObject *func = (FunctionObject*) self;
|
||||
|
||||
@@ -76,36 +74,36 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
||||
int expected_argc = func->argc;
|
||||
|
||||
if(expected_argc < (int) argc)
|
||||
{
|
||||
// Nothing to be done. By using
|
||||
// the right argc the additional
|
||||
// arguments are ignored implicitly.
|
||||
argv2 = argv;
|
||||
}
|
||||
{
|
||||
// Nothing to be done. By using
|
||||
// the right argc the additional
|
||||
// arguments are ignored implicitly.
|
||||
argv2 = argv;
|
||||
}
|
||||
else if(expected_argc > (int) argc)
|
||||
{
|
||||
// Some arguments are missing.
|
||||
argv2 = malloc(sizeof(Object*) * expected_argc);
|
||||
|
||||
if(argv2 == NULL)
|
||||
{
|
||||
// Some arguments are missing.
|
||||
argv2 = malloc(sizeof(Object*) * expected_argc);
|
||||
|
||||
if(argv2 == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the provided arguments.
|
||||
for(int i = 0; i < (int) argc; i += 1)
|
||||
argv2[i] = argv[i];
|
||||
|
||||
// Set the unspecified arguments to none.
|
||||
for(int i = argc; i < expected_argc; i += 1)
|
||||
{
|
||||
argv2[i] = Object_NewNone(heap, error);
|
||||
|
||||
if(argv2[i] == NULL)
|
||||
return 0;
|
||||
}
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the provided arguments.
|
||||
for(int i = 0; i < (int) argc; i += 1)
|
||||
argv2[i] = argv[i];
|
||||
|
||||
// Set the unspecified arguments to none.
|
||||
for(int i = argc; i < expected_argc; i += 1)
|
||||
{
|
||||
argv2[i] = Object_NewNone(heap, error);
|
||||
|
||||
if(argv2[i] == NULL)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
// The right amount of arguments was provided.
|
||||
argv2 = argv;
|
||||
@@ -176,10 +174,10 @@ Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, in
|
||||
Executable *exe_copy = Executable_Copy(exe);
|
||||
|
||||
if(exe_copy == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "Failed to copy executable");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "Failed to copy executable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func->runtime = runtime;
|
||||
func->exe = exe_copy;
|
||||
|
||||
+38
-38
@@ -64,48 +64,48 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
||||
int expected_argc = func->argc;
|
||||
|
||||
if(expected_argc < 0 || expected_argc == (int) argc)
|
||||
{
|
||||
// The function is variadic or the right
|
||||
// amount of arguments was provided.
|
||||
argv2 = argv;
|
||||
argc2 = argc;
|
||||
}
|
||||
{
|
||||
// The function is variadic or the right
|
||||
// amount of arguments was provided.
|
||||
argv2 = argv;
|
||||
argc2 = argc;
|
||||
}
|
||||
else if(expected_argc < (int) argc)
|
||||
{
|
||||
// Nothing to be done. By using
|
||||
// the right argc the additional
|
||||
// arguments are ignored implicitly.
|
||||
argv2 = argv;
|
||||
argc2 = expected_argc;
|
||||
}
|
||||
{
|
||||
// Nothing to be done. By using
|
||||
// the right argc the additional
|
||||
// arguments are ignored implicitly.
|
||||
argv2 = argv;
|
||||
argc2 = expected_argc;
|
||||
}
|
||||
else if(expected_argc > (int) argc)
|
||||
{
|
||||
// Some arguments are missing.
|
||||
argv2 = malloc(sizeof(Object*) * expected_argc);
|
||||
argc2 = expected_argc;
|
||||
|
||||
if(argv2 == NULL)
|
||||
{
|
||||
// Some arguments are missing.
|
||||
argv2 = malloc(sizeof(Object*) * expected_argc);
|
||||
argc2 = expected_argc;
|
||||
|
||||
if(argv2 == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the provided arguments.
|
||||
for(int i = 0; i < (int) argc; i += 1)
|
||||
argv2[i] = argv[i];
|
||||
|
||||
// Set the unspecified arguments to none.
|
||||
for(int i = argc; i < expected_argc; i += 1)
|
||||
{
|
||||
argv2[i] = Object_NewNone(heap, error);
|
||||
|
||||
if(argv2[i] == NULL)
|
||||
{
|
||||
free(argv2);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the provided arguments.
|
||||
for(int i = 0; i < (int) argc; i += 1)
|
||||
argv2[i] = argv[i];
|
||||
|
||||
// Set the unspecified arguments to none.
|
||||
for(int i = argc; i < expected_argc; i += 1)
|
||||
{
|
||||
argv2[i] = Object_NewNone(heap, error);
|
||||
|
||||
if(argv2[i] == NULL)
|
||||
{
|
||||
free(argv2);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else UNREACHABLE;
|
||||
|
||||
assert(func->callback != NULL);
|
||||
|
||||
+15
-15
@@ -120,22 +120,22 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
||||
|
||||
for(int i = 0; map->slots[i].name != NULL; i += 1)
|
||||
if(!strcmp(name, map->slots[i].name))
|
||||
{
|
||||
StaticMapSlot slot = map->slots[i];
|
||||
Object *obj;
|
||||
switch(slot.kind)
|
||||
{
|
||||
StaticMapSlot slot = map->slots[i];
|
||||
Object *obj;
|
||||
switch(slot.kind)
|
||||
{
|
||||
case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error);
|
||||
case SM_INT: return Object_FromInt(slot.as_int, heap, error);
|
||||
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
|
||||
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
|
||||
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
|
||||
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
|
||||
case SM_NONE: return Object_NewNone(heap, error);
|
||||
case SM_TYPE: return (Object*) slot.as_type;
|
||||
default: assert(0); break;
|
||||
}
|
||||
return obj;
|
||||
case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error);
|
||||
case SM_INT: return Object_FromInt(slot.as_int, heap, error);
|
||||
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
|
||||
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
|
||||
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
|
||||
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
|
||||
case SM_NONE: return Object_NewNone(heap, error);
|
||||
case SM_TYPE: return (Object*) slot.as_type;
|
||||
default: assert(0); break;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
+906
-907
File diff suppressed because it is too large
Load Diff
+32
-32
@@ -80,11 +80,11 @@ BPAlloc *BPAlloc_Init2(int first_size, int chunk_size,
|
||||
first_size = chunk_size;
|
||||
|
||||
if(fn_malloc == NULL)
|
||||
{
|
||||
userp = NULL;
|
||||
fn_malloc = default_fn_malloc;
|
||||
fn_free = default_fn_free;
|
||||
}
|
||||
{
|
||||
userp = NULL;
|
||||
fn_malloc = default_fn_malloc;
|
||||
fn_free = default_fn_free;
|
||||
}
|
||||
|
||||
void *temp = fn_malloc(userp, sizeof(BPAlloc) + sizeof(BPAllocChunk) + first_size + PADDING);
|
||||
|
||||
@@ -124,11 +124,11 @@ BPAlloc *BPAlloc_Init3(void *mem, int mem_size, int chunk_size,
|
||||
chunk_size = CHUNK_SIZE;
|
||||
|
||||
if(fn_malloc == NULL)
|
||||
{
|
||||
userp = NULL;
|
||||
fn_malloc = default_fn_malloc;
|
||||
fn_free = default_fn_free;
|
||||
}
|
||||
{
|
||||
userp = NULL;
|
||||
fn_malloc = default_fn_malloc;
|
||||
fn_free = default_fn_free;
|
||||
}
|
||||
|
||||
int required = sizeof(BPAlloc)
|
||||
+ sizeof(BPAllocChunk)
|
||||
@@ -170,14 +170,14 @@ void BPAlloc_Free(BPAlloc *alloc)
|
||||
BPAllocChunk *chunk = alloc->tail;
|
||||
|
||||
while(chunk->prev)
|
||||
{
|
||||
BPAllocChunk *prev = chunk->prev;
|
||||
{
|
||||
BPAllocChunk *prev = chunk->prev;
|
||||
|
||||
if(alloc->fn_free)
|
||||
alloc->fn_free(alloc->userp, chunk);
|
||||
if(alloc->fn_free)
|
||||
alloc->fn_free(alloc->userp, chunk);
|
||||
|
||||
chunk = prev;
|
||||
}
|
||||
chunk = prev;
|
||||
}
|
||||
|
||||
if(!(alloc->flags & FG_STATIC))
|
||||
if(alloc->fn_free)
|
||||
@@ -195,26 +195,26 @@ void *BPAlloc_Malloc(BPAlloc *alloc, int req_size)
|
||||
alloc->used = (alloc->used & ~7) + 8;
|
||||
|
||||
if(alloc->used + req_size > alloc->size)
|
||||
{
|
||||
// If the chunk size is lower than the
|
||||
// requested size, then set the chunk
|
||||
// size to the requested size.
|
||||
int chunk_size = MAX(alloc->minsize, req_size + PADDING);
|
||||
{
|
||||
// If the chunk size is lower than the
|
||||
// requested size, then set the chunk
|
||||
// size to the requested size.
|
||||
int chunk_size = MAX(alloc->minsize, req_size + PADDING);
|
||||
|
||||
assert(alloc->fn_malloc != NULL);
|
||||
BPAllocChunk *chunk = alloc->fn_malloc(alloc->userp, sizeof(BPAllocChunk) + chunk_size);
|
||||
assert(alloc->fn_malloc != NULL);
|
||||
BPAllocChunk *chunk = alloc->fn_malloc(alloc->userp, sizeof(BPAllocChunk) + chunk_size);
|
||||
|
||||
if(chunk == NULL)
|
||||
return NULL;
|
||||
if(chunk == NULL)
|
||||
return NULL;
|
||||
|
||||
chunk->prev = alloc->tail;
|
||||
alloc->tail = chunk;
|
||||
alloc->size = chunk_size;
|
||||
alloc->used = PADDING;
|
||||
chunk->prev = alloc->tail;
|
||||
alloc->tail = chunk;
|
||||
alloc->size = chunk_size;
|
||||
alloc->used = PADDING;
|
||||
|
||||
if(alloc->used & 7)
|
||||
alloc->used = (alloc->used & ~7) + 8;
|
||||
}
|
||||
if(alloc->used & 7)
|
||||
alloc->used = (alloc->used & ~7) + 8;
|
||||
}
|
||||
|
||||
void *addr = alloc->tail->body + alloc->used;
|
||||
|
||||
|
||||
+45
-45
@@ -109,42 +109,42 @@ _Bool BucketList_Append(BucketList *blist, const void *data, int size)
|
||||
int not_copied_yet = size;
|
||||
|
||||
while(not_copied_yet > 0)
|
||||
{
|
||||
// Copy until there's nothing left
|
||||
// or until the current bucket is
|
||||
// full. If the bucket is already
|
||||
// full, add another one.
|
||||
|
||||
int left_in_bucket = blist->tail->size - blist->tail->used;
|
||||
|
||||
if(left_in_bucket == 0)
|
||||
{
|
||||
// Copy until there's nothing left
|
||||
// or until the current bucket is
|
||||
// full. If the bucket is already
|
||||
// full, add another one.
|
||||
Bucket *new_bucket = make_bucket(blist->alloc, MIN_BUCKET_SIZE);
|
||||
|
||||
int left_in_bucket = blist->tail->size - blist->tail->used;
|
||||
if(new_bucket == NULL)
|
||||
return 0;
|
||||
|
||||
if(left_in_bucket == 0)
|
||||
{
|
||||
Bucket *new_bucket = make_bucket(blist->alloc, MIN_BUCKET_SIZE);
|
||||
|
||||
if(new_bucket == NULL)
|
||||
return 0;
|
||||
|
||||
append_bucket(blist, new_bucket);
|
||||
}
|
||||
|
||||
// Decide how much to copy.
|
||||
int copying = MIN(not_copied_yet, left_in_bucket);
|
||||
|
||||
// Copy into the bucket.
|
||||
{
|
||||
char *dst = blist->tail->body + blist->tail->used;
|
||||
|
||||
if(data == NULL)
|
||||
memset(dst, 0, copying);
|
||||
else
|
||||
memcpy(dst, data + size - not_copied_yet, copying);
|
||||
|
||||
blist->tail->used += copying;
|
||||
}
|
||||
|
||||
not_copied_yet -= copying;
|
||||
append_bucket(blist, new_bucket);
|
||||
}
|
||||
|
||||
// Decide how much to copy.
|
||||
int copying = MIN(not_copied_yet, left_in_bucket);
|
||||
|
||||
// Copy into the bucket.
|
||||
{
|
||||
char *dst = blist->tail->body + blist->tail->used;
|
||||
|
||||
if(data == NULL)
|
||||
memset(dst, 0, copying);
|
||||
else
|
||||
memcpy(dst, data + size - not_copied_yet, copying);
|
||||
|
||||
blist->tail->used += copying;
|
||||
}
|
||||
|
||||
not_copied_yet -= copying;
|
||||
}
|
||||
|
||||
blist->size += size;
|
||||
return 1;
|
||||
}
|
||||
@@ -158,16 +158,16 @@ void *BucketList_Append2(BucketList *blist, const void *data, int size)
|
||||
// current bucket, add another one with
|
||||
// enough space.
|
||||
if(blist->tail->used + size > blist->tail->size)
|
||||
{
|
||||
int bucket_size = MAX(MIN_BUCKET_SIZE, size);
|
||||
{
|
||||
int bucket_size = MAX(MIN_BUCKET_SIZE, size);
|
||||
|
||||
Bucket *new_bucket = make_bucket(blist->alloc, bucket_size);
|
||||
Bucket *new_bucket = make_bucket(blist->alloc, bucket_size);
|
||||
|
||||
if(new_bucket == NULL)
|
||||
return 0;
|
||||
if(new_bucket == NULL)
|
||||
return 0;
|
||||
|
||||
append_bucket(blist, new_bucket);
|
||||
}
|
||||
append_bucket(blist, new_bucket);
|
||||
}
|
||||
|
||||
void *addr = blist->tail->body + blist->tail->used;
|
||||
|
||||
@@ -195,15 +195,15 @@ void BucketList_Copy(BucketList *blist, void *dest, int len)
|
||||
Bucket *bucket = blist->head;
|
||||
|
||||
while(bucket && copied < len)
|
||||
{
|
||||
int copying = MIN(len - copied, bucket->used);
|
||||
assert(copying >= 0);
|
||||
{
|
||||
int copying = MIN(len - copied, bucket->used);
|
||||
assert(copying >= 0);
|
||||
|
||||
memcpy((char*) dest + copied, bucket->body, copying);
|
||||
memcpy((char*) dest + copied, bucket->body, copying);
|
||||
|
||||
copied += copying;
|
||||
bucket = bucket->next;
|
||||
}
|
||||
copied += copying;
|
||||
bucket = bucket->next;
|
||||
}
|
||||
}
|
||||
|
||||
BPAlloc *BucketList_GetAlloc(BucketList *blist)
|
||||
|
||||
+18
-18
@@ -87,29 +87,29 @@ void _Error_Report2(Error *err, _Bool internal,
|
||||
assert(p > -1);
|
||||
|
||||
if((unsigned int) p > sizeof(err->message2)-1)
|
||||
{
|
||||
char *temp = malloc(p+1);
|
||||
{
|
||||
char *temp = malloc(p+1);
|
||||
|
||||
if(temp == NULL)
|
||||
{
|
||||
err->truncated = 1;
|
||||
err->message = err->message2;
|
||||
err->length = sizeof(err->message2)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(temp, p+1, fmt, va2);
|
||||
err->truncated = 0;
|
||||
err->message = temp;
|
||||
err->length = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(temp == NULL)
|
||||
{
|
||||
err->truncated = 0;
|
||||
err->truncated = 1;
|
||||
err->message = err->message2;
|
||||
err->length = sizeof(err->message2)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(temp, p+1, fmt, va2);
|
||||
err->truncated = 0;
|
||||
err->message = temp;
|
||||
err->length = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err->truncated = 0;
|
||||
err->message = err->message2;
|
||||
err->length = p;
|
||||
}
|
||||
|
||||
va_end(va2);
|
||||
|
||||
|
||||
+21
-21
@@ -87,14 +87,14 @@ void Promise_Resolve(Promise *promise, const void *data, int size)
|
||||
|
||||
Gap *gap = promise->gaps;
|
||||
while(gap)
|
||||
{
|
||||
memcpy(gap->dest, data, size);
|
||||
{
|
||||
memcpy(gap->dest, data, size);
|
||||
|
||||
if(gap->callback)
|
||||
gap->callback(gap->userp);
|
||||
if(gap->callback)
|
||||
gap->callback(gap->userp);
|
||||
|
||||
gap = gap->next;
|
||||
}
|
||||
gap = gap->next;
|
||||
}
|
||||
|
||||
promise->gaps = NULL;
|
||||
}
|
||||
@@ -112,25 +112,25 @@ _Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callb
|
||||
assert(dest != NULL);
|
||||
|
||||
if(promise->set == 0)
|
||||
{
|
||||
Gap *gap = BPAlloc_Malloc(promise->alloc, sizeof(Gap));
|
||||
{
|
||||
Gap *gap = BPAlloc_Malloc(promise->alloc, sizeof(Gap));
|
||||
|
||||
if(gap == NULL)
|
||||
return 0;
|
||||
if(gap == NULL)
|
||||
return 0;
|
||||
|
||||
gap->next = promise->gaps;
|
||||
gap->dest = dest;
|
||||
gap->userp = userp;
|
||||
gap->callback = callback;
|
||||
promise->gaps = gap;
|
||||
}
|
||||
gap->next = promise->gaps;
|
||||
gap->dest = dest;
|
||||
gap->userp = userp;
|
||||
gap->callback = callback;
|
||||
promise->gaps = gap;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(dest, promise->body, promise->size);
|
||||
{
|
||||
memcpy(dest, promise->body, promise->size);
|
||||
|
||||
if(callback)
|
||||
callback(userp);
|
||||
}
|
||||
if(callback)
|
||||
callback(userp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+37
-37
@@ -86,36 +86,36 @@ Source *Source_FromFile(const char *file, Error *error)
|
||||
fp = fopen(file, "rb");
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
if(errno == ENOENT)
|
||||
Error_Report(error, 0, "File \"%s\" doesn't exist", file);
|
||||
else
|
||||
Error_Report(error, 1, "Call to fopen failed (%s, errno = %d)", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
if(errno == ENOENT)
|
||||
Error_Report(error, 0, "File \"%s\" doesn't exist", file);
|
||||
else
|
||||
Error_Report(error, 1, "Call to fopen failed (%s, errno = %d)", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(fseek(fp, 0, SEEK_END))
|
||||
{
|
||||
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = ftell(fp);
|
||||
|
||||
if(size < 0)
|
||||
{
|
||||
Error_Report(error, 1, "Call to ftell failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "Call to ftell failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(fseek(fp, 0, SEEK_SET))
|
||||
{
|
||||
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the source structure.
|
||||
@@ -126,11 +126,11 @@ Source *Source_FromFile(const char *file, Error *error)
|
||||
s = malloc(sizeof(Source) + namel + size + 2);
|
||||
|
||||
if(s == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->name = (char*) (s + 1);
|
||||
s->body = s->name + namel + 1;
|
||||
@@ -146,12 +146,12 @@ Source *Source_FromFile(const char *file, Error *error)
|
||||
int p = fread(s->body, 1, size, fp);
|
||||
|
||||
if(p != size)
|
||||
{
|
||||
Error_Report(error, 1, "Call to fread failed, %d bytes out of %d were read (%s, errno = %d)", p, size, strerror(errno), errno);
|
||||
fclose(fp);
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "Call to fread failed, %d bytes out of %d were read (%s, errno = %d)", p, size, strerror(errno), errno);
|
||||
fclose(fp);
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->body[s->size] = '\0';
|
||||
}
|
||||
@@ -172,10 +172,10 @@ Source *Source_FromString(const char *name, const char *body, int size, Error *e
|
||||
void *memory = malloc(sizeof(Source) + namel + size + 2);
|
||||
|
||||
if(memory == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
Error_Report(error, 1, "No memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Source *s = memory;
|
||||
s->name = (char*) (s + 1);
|
||||
|
||||
+8
-8
@@ -135,15 +135,15 @@ _Bool Stack_Push(Stack *s, void *item)
|
||||
Stack *Stack_Copy(Stack *s, _Bool readonly)
|
||||
{
|
||||
if(Stack_IsReadOnlyCopy(s))
|
||||
{
|
||||
// Reference is readonly,
|
||||
// so the copy must be
|
||||
// readonly.
|
||||
readonly = 1;
|
||||
{
|
||||
// Reference is readonly,
|
||||
// so the copy must be
|
||||
// readonly.
|
||||
readonly = 1;
|
||||
|
||||
// Remove readonly bit.
|
||||
s = unmark(s);
|
||||
}
|
||||
// Remove readonly bit.
|
||||
s = unmark(s);
|
||||
}
|
||||
|
||||
s->refs += 1;
|
||||
|
||||
|
||||
+110
-110
@@ -60,46 +60,46 @@
|
||||
int utf8_sequence_from_utf32_codepoint(char *utf8_data, int nbytes, uint32_t utf32_code)
|
||||
{
|
||||
if(utf32_code < 128)
|
||||
{
|
||||
if(nbytes < 1)
|
||||
return -1;
|
||||
{
|
||||
if(nbytes < 1)
|
||||
return -1;
|
||||
|
||||
utf8_data[0] = utf32_code;
|
||||
return 1;
|
||||
}
|
||||
utf8_data[0] = utf32_code;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(utf32_code < 2048)
|
||||
{
|
||||
if(nbytes < 2)
|
||||
return -1;
|
||||
{
|
||||
if(nbytes < 2)
|
||||
return -1;
|
||||
|
||||
utf8_data[0] = 0xc0 | (utf32_code >> 6);
|
||||
utf8_data[1] = 0x80 | (utf32_code & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
utf8_data[0] = 0xc0 | (utf32_code >> 6);
|
||||
utf8_data[1] = 0x80 | (utf32_code & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(utf32_code < 65536)
|
||||
{
|
||||
if(nbytes < 3)
|
||||
return -1;
|
||||
{
|
||||
if(nbytes < 3)
|
||||
return -1;
|
||||
|
||||
utf8_data[0] = 0xe0 | (utf32_code >> 12);
|
||||
utf8_data[1] = 0x80 | ((utf32_code >> 6) & 0x3f);
|
||||
utf8_data[2] = 0x80 | (utf32_code & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
utf8_data[0] = 0xe0 | (utf32_code >> 12);
|
||||
utf8_data[1] = 0x80 | ((utf32_code >> 6) & 0x3f);
|
||||
utf8_data[2] = 0x80 | (utf32_code & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if(utf32_code <= 0x10ffff)
|
||||
{
|
||||
if(nbytes < 4)
|
||||
return -1;
|
||||
{
|
||||
if(nbytes < 4)
|
||||
return -1;
|
||||
|
||||
utf8_data[0] = 0xf0 | (utf32_code >> 18);
|
||||
utf8_data[1] = 0x80 | ((utf32_code >> 12) & 0x3f);
|
||||
utf8_data[2] = 0x80 | ((utf32_code >> 6) & 0x3f);
|
||||
utf8_data[3] = 0x80 | (utf32_code & 0x3f);
|
||||
return 4;
|
||||
}
|
||||
utf8_data[0] = 0xf0 | (utf32_code >> 18);
|
||||
utf8_data[1] = 0x80 | ((utf32_code >> 12) & 0x3f);
|
||||
utf8_data[2] = 0x80 | ((utf32_code >> 6) & 0x3f);
|
||||
utf8_data[3] = 0x80 | (utf32_code & 0x3f);
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Code is out of range for UTF-8.
|
||||
return -1;
|
||||
@@ -148,71 +148,71 @@ int utf8_sequence_to_utf32_codepoint(const char *utf8_data, int nbytes, uint32_t
|
||||
return -1;
|
||||
|
||||
if(utf8_data[0] & 0x80)
|
||||
{
|
||||
// May be UTF-8.
|
||||
{
|
||||
// May be UTF-8.
|
||||
|
||||
if((unsigned char) utf8_data[0] >= 0xF0)
|
||||
{
|
||||
// 4 bytes.
|
||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
if((unsigned char) utf8_data[0] >= 0xF0)
|
||||
{
|
||||
// 4 bytes.
|
||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
|
||||
if(nbytes < 4)
|
||||
return -1;
|
||||
if(nbytes < 4)
|
||||
return -1;
|
||||
|
||||
uint32_t temp
|
||||
= (((uint32_t) utf8_data[0] & 0x07) << 18)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f) << 12)
|
||||
| (((uint32_t) utf8_data[2] & 0x3f) << 6)
|
||||
| (((uint32_t) utf8_data[3] & 0x3f));
|
||||
uint32_t temp
|
||||
= (((uint32_t) utf8_data[0] & 0x07) << 18)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f) << 12)
|
||||
| (((uint32_t) utf8_data[2] & 0x3f) << 6)
|
||||
| (((uint32_t) utf8_data[3] & 0x3f));
|
||||
|
||||
if(temp > 0x10ffff)
|
||||
return -1;
|
||||
if(temp > 0x10ffff)
|
||||
return -1;
|
||||
|
||||
*utf32_code = temp;
|
||||
return 4;
|
||||
}
|
||||
*utf32_code = temp;
|
||||
return 4;
|
||||
}
|
||||
|
||||
if((unsigned char) utf8_data[0] >= 0xE0)
|
||||
{
|
||||
// 3 bytes.
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
{
|
||||
// 3 bytes.
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
|
||||
if(nbytes < 3)
|
||||
return -1;
|
||||
if(nbytes < 3)
|
||||
return -1;
|
||||
|
||||
uint32_t temp
|
||||
= (((uint32_t) utf8_data[0] & 0x0f) << 12)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f) << 6)
|
||||
| (((uint32_t) utf8_data[2] & 0x3f));
|
||||
uint32_t temp
|
||||
= (((uint32_t) utf8_data[0] & 0x0f) << 12)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f) << 6)
|
||||
| (((uint32_t) utf8_data[2] & 0x3f));
|
||||
|
||||
if(temp > 0x10ffff)
|
||||
return -1;
|
||||
if(temp > 0x10ffff)
|
||||
return -1;
|
||||
|
||||
*utf32_code = temp;
|
||||
return 3;
|
||||
}
|
||||
*utf32_code = temp;
|
||||
return 3;
|
||||
}
|
||||
|
||||
if((unsigned char) utf8_data[0] >= 0xC0)
|
||||
{
|
||||
// 2 bytes.
|
||||
// 110xxxxx 10xxxxxx
|
||||
{
|
||||
// 2 bytes.
|
||||
// 110xxxxx 10xxxxxx
|
||||
|
||||
if(nbytes < 2)
|
||||
return -1;
|
||||
if(nbytes < 2)
|
||||
return -1;
|
||||
|
||||
*utf32_code
|
||||
= (((uint32_t) utf8_data[0] & 0x1f) << 6)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f));
|
||||
*utf32_code
|
||||
= (((uint32_t) utf8_data[0] & 0x1f) << 6)
|
||||
| (((uint32_t) utf8_data[1] & 0x3f));
|
||||
|
||||
assert(*utf32_code <= 0x10ffff);
|
||||
return 2;
|
||||
}
|
||||
assert(*utf32_code <= 0x10ffff);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// 1 byte
|
||||
// 10xxxxxx
|
||||
*utf32_code = (uint32_t) utf8_data[0] & 0x3f;
|
||||
return 1;
|
||||
}
|
||||
// 1 byte
|
||||
// 10xxxxxx
|
||||
*utf32_code = (uint32_t) utf8_data[0] & 0x3f;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// It's ASCII
|
||||
// 0xxxxxxx
|
||||
@@ -255,40 +255,40 @@ int utf8_strlen(const char *utf8_data, int nbytes)
|
||||
|
||||
int i = 0;
|
||||
while(i < nbytes)
|
||||
{
|
||||
{
|
||||
|
||||
#if ASSUME_ASCII
|
||||
{
|
||||
int ASCII_start = i;
|
||||
{
|
||||
int ASCII_start = i;
|
||||
|
||||
// Skip through ASCII
|
||||
while(i < nbytes && (utf8_data[i] & 0x80) == 0)
|
||||
i += 1;
|
||||
// Skip through ASCII
|
||||
while(i < nbytes && (utf8_data[i] & 0x80) == 0)
|
||||
i += 1;
|
||||
|
||||
int ASCII_end = i;
|
||||
int ASCII_end = i;
|
||||
|
||||
len += (ASCII_end - ASCII_start);
|
||||
len += (ASCII_end - ASCII_start);
|
||||
|
||||
// Either we scanned through all of the
|
||||
// string, or we encountered some unicode.
|
||||
// Either we scanned through all of the
|
||||
// string, or we encountered some unicode.
|
||||
|
||||
if(i == nbytes)
|
||||
// String ended.
|
||||
break;
|
||||
}
|
||||
if(i == nbytes)
|
||||
// String ended.
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Found unicode.
|
||||
{
|
||||
int n = utf8_sequence_to_utf32_codepoint(utf8_data + i, nbytes - i, NULL);
|
||||
// Found unicode.
|
||||
{
|
||||
int n = utf8_sequence_to_utf32_codepoint(utf8_data + i, nbytes - i, NULL);
|
||||
|
||||
if(n < 1)
|
||||
return -1;
|
||||
if(n < 1)
|
||||
return -1;
|
||||
|
||||
i += n;
|
||||
len += 1;
|
||||
}
|
||||
i += n;
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -347,11 +347,11 @@ int utf8_prev(const char *utf8_data, int nbytes, int idx, uint32_t *utf32_code)
|
||||
// to go faster.
|
||||
|
||||
if((utf8_data[tail] & 0x80) == 0)
|
||||
{
|
||||
if(utf32_code)
|
||||
*utf32_code = utf8_data[tail];
|
||||
return tail;
|
||||
}
|
||||
{
|
||||
if(utf32_code)
|
||||
*utf32_code = utf8_data[tail];
|
||||
return tail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -362,11 +362,11 @@ int utf8_prev(const char *utf8_data, int nbytes, int idx, uint32_t *utf32_code)
|
||||
idx -= 1;
|
||||
|
||||
if(idx == -1)
|
||||
{
|
||||
// No head sequence byte was found,
|
||||
// so this isn't valid UTF-8.
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
// No head sequence byte was found,
|
||||
// so this isn't valid UTF-8.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The index of the head byte.
|
||||
int head = idx;
|
||||
|
||||
Reference in New Issue
Block a user