aboutsummaryrefslogtreecommitdiff
path: root/builtins
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-08 17:17:15 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-08 17:17:15 -0400
commitaeed1992e94c5ab6a5104a06a921101fbe8f40ed (patch)
tree8ba6dc531acefa0eedd330224f16f750496e8dbe /builtins
parentcf9d5b1619b9e5e886d2754f167046ff77d36abf (diff)
Fix nearly every GCC warning and add __attribute__((pure/const)) where
appropriate
Diffstat (limited to 'builtins')
-rw-r--r--builtins/array.c104
-rw-r--r--builtins/array.h16
-rw-r--r--builtins/bool.c2
-rw-r--r--builtins/bool.h3
-rw-r--r--builtins/c_string.c6
-rw-r--r--builtins/c_string.h6
-rw-r--r--builtins/channel.c8
-rw-r--r--builtins/channel.h6
-rw-r--r--builtins/datatypes.h2
-rw-r--r--builtins/files.c8
-rw-r--r--builtins/functions.c40
-rw-r--r--builtins/functions.h13
-rw-r--r--builtins/integers.c40
-rw-r--r--builtins/integers.h65
-rw-r--r--builtins/nums.c40
-rw-r--r--builtins/nums.h33
-rw-r--r--builtins/pointer.c4
-rw-r--r--builtins/pointer.h5
-rw-r--r--builtins/range.c8
-rw-r--r--builtins/range.h4
-rw-r--r--builtins/shell.c2
-rw-r--r--builtins/siphash-internals.h2
-rw-r--r--builtins/siphash.c5
-rw-r--r--builtins/table.c78
-rw-r--r--builtins/table.h20
-rw-r--r--builtins/text.c342
-rw-r--r--builtins/text.h13
-rw-r--r--builtins/types.h1
-rw-r--r--builtins/util.c3
-rw-r--r--builtins/util.h10
30 files changed, 463 insertions, 426 deletions
diff --git a/builtins/array.c b/builtins/array.c
index f09af917..a6786e0f 100644
--- a/builtins/array.c
+++ b/builtins/array.c
@@ -22,7 +22,7 @@
#include "siphash.h"
#include "siphash-internals.h"
-static inline int64_t get_padded_item_size(const TypeInfo *info)
+PUREFUNC static inline int64_t get_padded_item_size(const TypeInfo *info)
{
int64_t size = info->ArrayInfo.item->size;
if (info->ArrayInfo.item->align > 1 && size % info->ArrayInfo.item->align)
@@ -36,12 +36,13 @@ public void Array$compact(Array_t *arr, int64_t padded_item_size)
{
void *copy = NULL;
if (arr->length > 0) {
- copy = arr->atomic ? GC_MALLOC_ATOMIC(arr->length * padded_item_size) : GC_MALLOC(arr->length * padded_item_size);
+ copy = arr->atomic ? GC_MALLOC_ATOMIC((size_t)arr->length * (size_t)padded_item_size)
+ : GC_MALLOC((size_t)arr->length * (size_t)padded_item_size);
if ((int64_t)arr->stride == padded_item_size) {
- memcpy(copy, arr->data, arr->length * padded_item_size);
+ memcpy(copy, arr->data, (size_t)arr->length * (size_t)padded_item_size);
} else {
for (int64_t i = 0; i < arr->length; i++)
- memcpy(copy + i*padded_item_size, arr->data + arr->stride*i, padded_item_size);
+ memcpy(copy + i*padded_item_size, arr->data + arr->stride*i, (size_t)padded_item_size);
}
}
*arr = (Array_t){
@@ -63,15 +64,17 @@ public void Array$insert(Array_t *arr, const void *item, Int_t int_index, int64_
if (!arr->data) {
arr->free = 4;
- arr->data = arr->atomic ? GC_MALLOC_ATOMIC(arr->free * padded_item_size) : GC_MALLOC(arr->free * padded_item_size);
+ arr->data = arr->atomic ? GC_MALLOC_ATOMIC((size_t)arr->free * (size_t)padded_item_size)
+ : GC_MALLOC((size_t)arr->free * (size_t)padded_item_size);
arr->stride = padded_item_size;
} else if (arr->free < 1 || arr->data_refcount != 0 || (int64_t)arr->stride != padded_item_size) {
arr->free = MIN(ARRAY_MAX_FREE_ENTRIES, MAX(8, arr->length/4));
- void *copy = arr->atomic ? GC_MALLOC_ATOMIC((arr->length + arr->free) * padded_item_size) : GC_MALLOC((arr->length + arr->free) * padded_item_size);
+ void *copy = arr->atomic ? GC_MALLOC_ATOMIC((size_t)(arr->length + arr->free) * (size_t)padded_item_size)
+ : GC_MALLOC((size_t)(arr->length + arr->free) * (size_t)padded_item_size);
for (int64_t i = 0; i < index-1; i++)
- memcpy(copy + i*padded_item_size, arr->data + arr->stride*i, padded_item_size);
+ memcpy(copy + i*padded_item_size, arr->data + arr->stride*i, (size_t)padded_item_size);
for (int64_t i = index-1; i < (int64_t)arr->length; i++)
- memcpy(copy + (i+1)*padded_item_size, arr->data + arr->stride*i, padded_item_size);
+ memcpy(copy + (i+1)*padded_item_size, arr->data + arr->stride*i, (size_t)padded_item_size);
arr->data = copy;
arr->data_refcount = 0;
arr->stride = padded_item_size;
@@ -80,12 +83,12 @@ public void Array$insert(Array_t *arr, const void *item, Int_t int_index, int64_
memmove(
arr->data + index*padded_item_size,
arr->data + (index-1)*padded_item_size,
- (arr->length - index + 1)*padded_item_size);
+ (size_t)((arr->length - index + 1)*padded_item_size));
}
assert(arr->free > 0);
--arr->free;
++arr->length;
- memcpy((void*)arr->data + (index-1)*padded_item_size, item, padded_item_size);
+ memcpy((void*)arr->data + (index-1)*padded_item_size, item, (size_t)padded_item_size);
}
public void Array$insert_all(Array_t *arr, Array_t to_insert, Int_t int_index, int64_t padded_item_size)
@@ -115,43 +118,43 @@ public void Array$insert_all(Array_t *arr, Array_t to_insert, Int_t int_index, i
if (index != arr->length+1)
memmove((void*)arr->data + index*padded_item_size,
arr->data + (index-1)*padded_item_size,
- (arr->length - index + to_insert.length-1)*padded_item_size);
+ (size_t)((arr->length - index + to_insert.length-1)*padded_item_size));
for (int64_t i = 0; i < to_insert.length; i++)
memcpy((void*)arr->data + (index-1 + i)*padded_item_size,
- to_insert.data + i*to_insert.stride, padded_item_size);
+ to_insert.data + i*to_insert.stride, (size_t)padded_item_size);
} else {
// Otherwise, allocate a new chunk of memory for the array and populate it:
int64_t new_len = arr->length + to_insert.length;
arr->free = MIN(ARRAY_MAX_FREE_ENTRIES, MAX(8, new_len/4));
- void *data = arr->atomic ? GC_MALLOC_ATOMIC((new_len + arr->free) * padded_item_size)
- : GC_MALLOC((new_len + arr->free) * padded_item_size);
+ void *data = arr->atomic ? GC_MALLOC_ATOMIC((size_t)((new_len + arr->free) * padded_item_size))
+ : GC_MALLOC((size_t)((new_len + arr->free) * padded_item_size));
void *p = data;
// Copy first chunk of `arr` if needed:
if (index > 1) {
if (arr->stride == padded_item_size) {
- p = mempcpy(p, arr->data, (index-1)*padded_item_size);
+ p = mempcpy(p, arr->data, (size_t)((index-1)*padded_item_size));
} else {
for (int64_t i = 0; i < index-1; i++)
- p = mempcpy(p, arr->data + arr->stride*i, padded_item_size);
+ p = mempcpy(p, arr->data + arr->stride*i, (size_t)padded_item_size);
}
}
// Copy `to_insert`
if (to_insert.stride == padded_item_size) {
- p = mempcpy(p, to_insert.data, to_insert.length*padded_item_size);
+ p = mempcpy(p, to_insert.data, (size_t)(to_insert.length*padded_item_size));
} else {
for (int64_t i = 0; i < index-1; i++)
- p = mempcpy(p, to_insert.data + to_insert.stride*i, padded_item_size);
+ p = mempcpy(p, to_insert.data + to_insert.stride*i, (size_t)padded_item_size);
}
// Copy last chunk of `arr` if needed:
if (index < arr->length + 1) {
if (arr->stride == padded_item_size) {
- p = mempcpy(p, arr->data + padded_item_size*(index-1), (arr->length - index + 1)*padded_item_size);
+ p = mempcpy(p, arr->data + padded_item_size*(index-1), (size_t)((arr->length - index + 1)*padded_item_size));
} else {
for (int64_t i = index-1; i < arr->length-1; i++)
- p = mempcpy(p, arr->data + arr->stride*i, padded_item_size);
+ p = mempcpy(p, arr->data + arr->stride*i, (size_t)padded_item_size);
}
}
arr->length = new_len;
@@ -178,10 +181,11 @@ public void Array$remove_at(Array_t *arr, Int_t int_index, Int_t int_count, int6
if (arr->free >= 0)
arr->free += count;
} else if (arr->data_refcount != 0 || (int64_t)arr->stride != padded_item_size) {
- void *copy = arr->atomic ? GC_MALLOC_ATOMIC((arr->length-1) * padded_item_size) : GC_MALLOC((arr->length-1) * padded_item_size);
+ void *copy = arr->atomic ? GC_MALLOC_ATOMIC((size_t)((arr->length-1) * padded_item_size))
+ : GC_MALLOC((size_t)((arr->length-1) * padded_item_size));
for (int64_t src = 1, dest = 1; src <= (int64_t)arr->length; src++) {
if (src < index || src >= index + count) {
- memcpy(copy + (dest - 1)*padded_item_size, arr->data + arr->stride*(src - 1), padded_item_size);
+ memcpy(copy + (dest - 1)*padded_item_size, arr->data + arr->stride*(src - 1), (size_t)padded_item_size);
++dest;
}
}
@@ -189,7 +193,8 @@ public void Array$remove_at(Array_t *arr, Int_t int_index, Int_t int_count, int6
arr->free = 0;
arr->data_refcount = 0;
} else {
- memmove((void*)arr->data + (index-1)*padded_item_size, arr->data + (index-1 + count)*padded_item_size, (arr->length - index + count - 1)*padded_item_size);
+ memmove((void*)arr->data + (index-1)*padded_item_size, arr->data + (index-1 + count)*padded_item_size,
+ (size_t)((arr->length - index + count - 1)*padded_item_size));
arr->free += count;
}
arr->length -= count;
@@ -241,16 +246,17 @@ public void Array$sort(Array_t *arr, closure_t comparison, int64_t padded_item_s
if (arr->data_refcount != 0 || (int64_t)arr->stride != padded_item_size)
Array$compact(arr, padded_item_size);
- qsort_r(arr->data, arr->length, padded_item_size, comparison.fn, comparison.userdata);
+ qsort_r(arr->data, (size_t)arr->length, (size_t)padded_item_size, comparison.fn, comparison.userdata);
}
public Array_t Array$sorted(Array_t arr, closure_t comparison, int64_t padded_item_size)
{
Array$compact(&arr, padded_item_size);
- qsort_r(arr.data, arr.length, padded_item_size, comparison.fn, comparison.userdata);
+ qsort_r(arr.data, (size_t)arr.length, (size_t)padded_item_size, comparison.fn, comparison.userdata);
return arr;
}
+#pragma GCC diagnostic ignored "-Wstack-protector"
public void Array$shuffle(Array_t *arr, int64_t padded_item_size)
{
if (arr->data_refcount != 0 || (int64_t)arr->stride != padded_item_size)
@@ -259,9 +265,9 @@ public void Array$shuffle(Array_t *arr, int64_t padded_item_size)
char tmp[padded_item_size];
for (int64_t i = arr->length-1; i > 1; i--) {
int64_t j = arc4random_uniform(i+1);
- memcpy(tmp, arr->data + i*padded_item_size, padded_item_size);
- memcpy((void*)arr->data + i*padded_item_size, arr->data + j*padded_item_size, padded_item_size);
- memcpy((void*)arr->data + j*padded_item_size, tmp, padded_item_size);
+ memcpy(tmp, arr->data + i*padded_item_size, (size_t)padded_item_size);
+ memcpy((void*)arr->data + i*padded_item_size, arr->data + j*padded_item_size, (size_t)padded_item_size);
+ memcpy((void*)arr->data + j*padded_item_size, tmp, (size_t)padded_item_size);
}
}
@@ -301,7 +307,7 @@ public Array_t Array$sample(Array_t arr, Int_t int_n, Array_t weights, int64_t p
return (Array_t){};
Array_t selected = {
- .data=arr.atomic ? GC_MALLOC_ATOMIC(n * padded_item_size) : GC_MALLOC(n * padded_item_size),
+ .data=arr.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size)) : GC_MALLOC((size_t)(n * padded_item_size)),
.length=n,
.stride=padded_item_size, .atomic=arr.atomic};
@@ -324,7 +330,7 @@ public Array_t Array$sample(Array_t arr, Int_t int_n, Array_t weights, int64_t p
if (total == 0.0) {
for (int64_t i = 0; i < n; i++) {
int64_t index = arc4random_uniform(arr.length);
- memcpy(selected.data + i*padded_item_size, arr.data + arr.stride*index, padded_item_size);
+ memcpy(selected.data + i*padded_item_size, arr.data + arr.stride*index, (size_t)padded_item_size);
}
} else {
double inverse_average = (double)arr.length / total;
@@ -367,7 +373,7 @@ public Array_t Array$sample(Array_t arr, Int_t int_n, Array_t weights, int64_t p
int64_t index = (int64_t)r;
if ((r - (double)index) > aliases[index].odds)
index = aliases[index].alias;
- memcpy(selected.data + i*selected.stride, arr.data + index*arr.stride, padded_item_size);
+ memcpy(selected.data + i*selected.stride, arr.data + index*arr.stride, (size_t)padded_item_size);
}
}
return selected;
@@ -421,10 +427,10 @@ public Array_t Array$by(Array_t array, Int_t int_stride, int64_t padded_item_siz
void *copy = NULL;
int64_t len = (stride < 0 ? array.length / -stride : array.length / stride) + ((array.length % stride) != 0);
if (len > 0) {
- copy = array.atomic ? GC_MALLOC_ATOMIC(len * padded_item_size) : GC_MALLOC(len * padded_item_size);
+ copy = array.atomic ? GC_MALLOC_ATOMIC((size_t)(len * padded_item_size)) : GC_MALLOC((size_t)(len * padded_item_size));
void *start = (stride < 0 ? array.data + (array.stride * (array.length - 1)) : array.data);
for (int64_t i = 0; i < len; i++)
- memcpy(copy + i*padded_item_size, start + array.stride*stride*i, padded_item_size);
+ memcpy(copy + i*padded_item_size, start + array.stride*stride*i, (size_t)padded_item_size);
}
return (Array_t){
.data=copy,
@@ -463,19 +469,20 @@ public Array_t Array$reversed(Array_t array, int64_t padded_item_size)
public Array_t Array$concat(Array_t x, Array_t y, int64_t padded_item_size)
{
- void *data = x.atomic ? GC_MALLOC_ATOMIC(padded_item_size*(x.length + y.length)) : GC_MALLOC(padded_item_size*(x.length + y.length));
+ void *data = x.atomic ? GC_MALLOC_ATOMIC((size_t)(padded_item_size*(x.length + y.length)))
+ : GC_MALLOC((size_t)(padded_item_size*(x.length + y.length)));
if (x.stride == padded_item_size) {
- memcpy(data, x.data, padded_item_size*x.length);
+ memcpy(data, x.data, (size_t)(padded_item_size*x.length));
} else {
for (int64_t i = 0; i < x.length; i++)
- memcpy(data + i*padded_item_size, x.data + i*padded_item_size, padded_item_size);
+ memcpy(data + i*padded_item_size, x.data + i*padded_item_size, (size_t)padded_item_size);
}
if (y.stride == padded_item_size) {
- memcpy(data + padded_item_size*x.length, y.data, padded_item_size*y.length);
+ memcpy(data + padded_item_size*x.length, y.data, (size_t)(padded_item_size*y.length));
} else {
for (int64_t i = 0; i < x.length; i++)
- memcpy(data + (x.length + i)*padded_item_size, y.data + i*padded_item_size, padded_item_size);
+ memcpy(data + (x.length + i)*padded_item_size, y.data + i*padded_item_size, (size_t)padded_item_size);
}
return (Array_t){
@@ -514,11 +521,11 @@ public int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo
item_padded_size += type->ArrayInfo.item->align - (item_padded_size % type->ArrayInfo.item->align); // padding
if ((int64_t)x->stride == item_padded_size && (int64_t)y->stride == item_padded_size && item->size == item_padded_size) {
- int32_t cmp = (int32_t)memcmp(x->data, y->data, MIN(x->length, y->length)*item_padded_size);
+ int32_t cmp = (int32_t)memcmp(x->data, y->data, (size_t)(MIN(x->length, y->length)*item_padded_size));
if (cmp != 0) return cmp;
} else {
for (int32_t i = 0, len = MIN(x->length, y->length); i < len; i++) {
- int32_t cmp = (int32_t)memcmp(x->data+ x->stride*i, y->data + y->stride*i, item->size);
+ int32_t cmp = (int32_t)memcmp(x->data+ x->stride*i, y->data + y->stride*i, (size_t)(item->size));
if (cmp != 0) return cmp;
}
}
@@ -533,7 +540,7 @@ public int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo
public bool Array$equal(const Array_t *x, const Array_t *y, const TypeInfo *type)
{
- return (Array$compare(x, y, type) == 0);
+ return x == y || (x->length == y->length && Array$compare(x, y, type) == 0);
}
public Text_t Array$as_text(const Array_t *arr, bool colorize, const TypeInfo *type)
@@ -570,11 +577,12 @@ public uint64_t Array$hash(const Array_t *arr, const TypeInfo *type)
return siphashfinish_last_part(&sh, 0);
}
+#pragma GCC diagnostic ignored "-Wstack-protector"
static void siftdown(Array_t *heap, int64_t startpos, int64_t pos, closure_t comparison, int64_t padded_item_size)
{
assert(pos > 0 && pos < heap->length);
char newitem[padded_item_size];
- memcpy(newitem, heap->data + heap->stride*pos, padded_item_size);
+ memcpy(newitem, heap->data + heap->stride*pos, (size_t)(padded_item_size));
while (pos > startpos) {
int64_t parentpos = (pos - 1) >> 1;
typedef int32_t (*cmp_fn_t)(void*, void*, void*);
@@ -582,10 +590,10 @@ static void siftdown(Array_t *heap, int64_t startpos, int64_t pos, closure_t com
if (cmp >= 0)
break;
- memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*parentpos, padded_item_size);
+ memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*parentpos, (size_t)(padded_item_size));
pos = parentpos;
}
- memcpy(heap->data + heap->stride*pos, newitem, padded_item_size);
+ memcpy(heap->data + heap->stride*pos, newitem, (size_t)(padded_item_size));
}
static void siftup(Array_t *heap, int64_t pos, closure_t comparison, int64_t padded_item_size)
@@ -595,7 +603,7 @@ static void siftup(Array_t *heap, int64_t pos, closure_t comparison, int64_t pad
assert(pos < endpos);
char old_top[padded_item_size];
- memcpy(old_top, heap->data + heap->stride*pos, padded_item_size);
+ memcpy(old_top, heap->data + heap->stride*pos, (size_t)(padded_item_size));
// Bubble up the smallest leaf node
int64_t limit = endpos >> 1;
while (pos < limit) {
@@ -610,10 +618,10 @@ static void siftup(Array_t *heap, int64_t pos, closure_t comparison, int64_t pad
}
// Move the child node up:
- memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*childpos, padded_item_size);
+ memcpy(heap->data + heap->stride*pos, heap->data + heap->stride*childpos, (size_t)(padded_item_size));
pos = childpos;
}
- memcpy(heap->data + heap->stride*pos, old_top, padded_item_size);
+ memcpy(heap->data + heap->stride*pos, old_top, (size_t)(padded_item_size));
// Shift the node's parents down:
siftdown(heap, startpos, pos, comparison, padded_item_size);
}
@@ -642,7 +650,7 @@ public void Array$heap_pop(Array_t *heap, closure_t comparison, int64_t padded_i
} else {
if (heap->data_refcount != 0)
Array$compact(heap, padded_item_size);
- memcpy(heap->data, heap->data + heap->stride*(heap->length-1), padded_item_size);
+ memcpy(heap->data, heap->data + heap->stride*(heap->length-1), (size_t)(padded_item_size));
--heap->length;
siftup(heap, 0, comparison, padded_item_size);
}
diff --git a/builtins/array.h b/builtins/array.h
index 98e949c8..99a892fc 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -80,16 +80,16 @@ Array_t Array$sample(Array_t arr, Int_t n, Array_t weights, int64_t padded_item_
Table_t Array$counts(Array_t arr, const TypeInfo *type);
void Array$clear(Array_t *array);
void Array$compact(Array_t *arr, int64_t padded_item_size);
-bool Array$has(Array_t array, void *item, const TypeInfo *type);
+PUREFUNC bool Array$has(Array_t array, void *item, const TypeInfo *type);
#define Array$has_value(arr, item_expr, type) ({ __typeof(item_expr) item = item_expr; Array$has(arr, &item, type); })
-Array_t Array$from(Array_t array, Int_t first);
-Array_t Array$to(Array_t array, Int_t last);
-Array_t Array$by(Array_t array, Int_t stride, int64_t padded_item_size);
-Array_t Array$reversed(Array_t array, int64_t padded_item_size);
+PUREFUNC Array_t Array$from(Array_t array, Int_t first);
+PUREFUNC Array_t Array$to(Array_t array, Int_t last);
+PUREFUNC Array_t Array$by(Array_t array, Int_t stride, int64_t padded_item_size);
+PUREFUNC Array_t Array$reversed(Array_t array, int64_t padded_item_size);
Array_t Array$concat(Array_t x, Array_t y, int64_t padded_item_size);
-uint64_t Array$hash(const Array_t *arr, const TypeInfo *type);
-int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo *type);
-bool Array$equal(const Array_t *x, const Array_t *y, const TypeInfo *type);
+PUREFUNC uint64_t Array$hash(const Array_t *arr, const TypeInfo *type);
+PUREFUNC int32_t Array$compare(const Array_t *x, const Array_t *y, const TypeInfo *type);
+PUREFUNC bool Array$equal(const Array_t *x, const Array_t *y, const TypeInfo *type);
Text_t Array$as_text(const Array_t *arr, bool colorize, const TypeInfo *type);
void Array$heapify(Array_t *heap, closure_t comparison, int64_t padded_item_size);
void Array$heap_push(Array_t *heap, const void *item, closure_t comparison, int64_t padded_item_size);
diff --git a/builtins/bool.c b/builtins/bool.c
index 677cfd97..63eb73f9 100644
--- a/builtins/bool.c
+++ b/builtins/bool.c
@@ -13,7 +13,7 @@
#include "types.h"
#include "util.h"
-public Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo *type)
+PUREFUNC public Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo *type)
{
(void)type;
if (!b) return Text("Bool");
diff --git a/builtins/bool.h b/builtins/bool.h
index cf2237fd..5f222c49 100644
--- a/builtins/bool.h
+++ b/builtins/bool.h
@@ -7,12 +7,13 @@
#include <stdint.h>
#include "types.h"
+#include "util.h"
#define Bool_t bool
#define yes (Bool_t)true
#define no (Bool_t)false
-Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo *type);
+PUREFUNC Text_t Bool$as_text(const bool *b, bool colorize, const TypeInfo *type);
bool Bool$from_text(Text_t text, bool *success);
Bool_t Bool$random(double p);
diff --git a/builtins/c_string.c b/builtins/c_string.c
index d916bfa9..3e3ef740 100644
--- a/builtins/c_string.c
+++ b/builtins/c_string.c
@@ -21,7 +21,7 @@ public Text_t CString$as_text(const void *c_string, bool colorize, const TypeInf
return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("), Text$quoted(text, colorize), Text(")"));
}
-public int32_t CString$compare(const char **x, const char **y)
+PUREFUNC public int32_t CString$compare(const char **x, const char **y)
{
if (x == y)
return 0;
@@ -32,12 +32,12 @@ public int32_t CString$compare(const char **x, const char **y)
return strcmp(*x, *y);
}
-public bool CString$equal(const char **x, const char **y)
+PUREFUNC public bool CString$equal(const char **x, const char **y)
{
return CString$compare(x, y) == 0;
}
-public uint64_t CString$hash(const char **c_str)
+PUREFUNC public uint64_t CString$hash(const char **c_str)
{
if (!*c_str) return 0;
return siphash24((void*)*c_str, strlen(*c_str));
diff --git a/builtins/c_string.h b/builtins/c_string.h
index 76c74c23..10621e62 100644
--- a/builtins/c_string.h
+++ b/builtins/c_string.h
@@ -9,9 +9,9 @@
#include "types.h"
Text_t CString$as_text(const void *str, bool colorize, const TypeInfo *info);
-int CString$compare(const char **x, const char **y);
-bool CString$equal(const char **x, const char **y);
-uint64_t CString$hash(const char **str);
+PUREFUNC int CString$compare(const char **x, const char **y);
+PUREFUNC bool CString$equal(const char **x, const char **y);
+PUREFUNC uint64_t CString$hash(const char **str);
extern const TypeInfo CString$info;
diff --git a/builtins/channel.c b/builtins/channel.c
index e877b6b5..b5868ee6 100644
--- a/builtins/channel.c
+++ b/builtins/channel.c
@@ -65,7 +65,7 @@ public void Channel$get(channel_t *channel, void *out, bool front, int64_t item_
(void)pthread_mutex_lock(&channel->mutex);
while (channel->items.length == 0)
pthread_cond_wait(&channel->cond, &channel->mutex);
- memcpy(out, channel->items.data + channel->items.stride * (front ? 0 : channel->items.length-1), item_size);
+ memcpy(out, channel->items.data + channel->items.stride * (front ? 0 : channel->items.length-1), (size_t)(item_size));
Int_t index = front ? I_small(1) : Int64_to_Int(channel->items.length);
Array$remove_at(&channel->items, index, I_small(1), padded_item_size);
(void)pthread_mutex_unlock(&channel->mutex);
@@ -78,7 +78,7 @@ public void Channel$peek(channel_t *channel, void *out, bool front, int64_t item
while (channel->items.length == 0)
pthread_cond_wait(&channel->cond, &channel->mutex);
int64_t index = front ? 0 : channel->items.length-1;
- memcpy(out, channel->items.data + channel->items.stride*index, item_size);
+ memcpy(out, channel->items.data + channel->items.stride*index, (size_t)(item_size));
(void)pthread_mutex_unlock(&channel->mutex);
(void)pthread_cond_signal(&channel->cond);
}
@@ -106,13 +106,13 @@ public uint64_t Channel$hash(const channel_t **channel, const TypeInfo *type)
return siphash24((void*)*channel, sizeof(channel_t*));
}
-public int32_t Channel$compare(const channel_t **x, const channel_t **y, const TypeInfo *type)
+PUREFUNC public int32_t Channel$compare(const channel_t **x, const channel_t **y, const TypeInfo *type)
{
(void)type;
return (*x > *y) - (*x < *y);
}
-bool Channel$equal(const channel_t **x, const channel_t **y, const TypeInfo *type)
+PUREFUNC bool Channel$equal(const channel_t **x, const channel_t **y, const TypeInfo *type)
{
(void)type;
return (*x == *y);
diff --git a/builtins/channel.h b/builtins/channel.h
index 89711045..5eaf2a19 100644
--- a/builtins/channel.h
+++ b/builtins/channel.h
@@ -21,9 +21,9 @@ void Channel$peek(channel_t *channel, void *out, bool front, int64_t item_size);
#define Channel$peek_value(channel, front, t) ({ t _val; Channel$peek(channel, &_val, front, sizeof(t)); _val; })
void Channel$clear(channel_t *channel);
Array_t Channel$view(channel_t *channel);
-uint64_t Channel$hash(const channel_t **channel, const TypeInfo *type);
-int32_t Channel$compare(const channel_t **x, const channel_t **y, const TypeInfo *type);
-bool Channel$equal(const channel_t **x, const channel_t **y, const TypeInfo *type);
+PUREFUNC uint64_t Channel$hash(const channel_t **channel, const TypeInfo *type);
+PUREFUNC int32_t Channel$compare(const channel_t **x, const channel_t **y, const TypeInfo *type);
+PUREFUNC bool Channel$equal(const channel_t **x, const channel_t **y, const TypeInfo *type);
Text_t Channel$as_text(const channel_t **channel, bool colorize, const TypeInfo *type);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/datatypes.h b/builtins/datatypes.h
index f7cc23ee..aa7670b7 100644
--- a/builtins/datatypes.h
+++ b/builtins/datatypes.h
@@ -47,7 +47,7 @@ typedef struct {
typedef struct {
uint32_t count:31, last_free:31;
uint8_t data_refcount:2;
- bucket_t buckets[0];
+ bucket_t buckets[];
} bucket_info_t;
typedef struct table_s {
diff --git a/builtins/files.c b/builtins/files.c
index dc91d0b0..6ff3f988 100644
--- a/builtins/files.c
+++ b/builtins/files.c
@@ -94,8 +94,8 @@ static file_t *_load_file(const char* filename, FILE *file)
while ((line_len = getline(&line_buf, &line_cap, file)) >= 0) {
if (ret->line_capacity <= ret->num_lines)
ret->line_offsets = GC_REALLOC(ret->line_offsets, sizeof(int64_t[ret->line_capacity += 32]));
- ret->line_offsets[ret->num_lines++] = file_size;
- fwrite(line_buf, sizeof(char), line_len, mem);
+ ret->line_offsets[ret->num_lines++] = (int64_t)file_size;
+ fwrite(line_buf, sizeof(char), (size_t)line_len, mem);
fflush(mem);
}
fclose(file);
@@ -104,7 +104,7 @@ static file_t *_load_file(const char* filename, FILE *file)
memcpy(copy, file_buf, file_size);
copy[file_size] = '\0';
ret->text = copy;
- ret->len = file_size;
+ ret->len = (int64_t)file_size;
fclose(mem);
free(file_buf);
@@ -114,7 +114,7 @@ static file_t *_load_file(const char* filename, FILE *file)
// Convert to relative path (if applicable)
char buf[PATH_MAX];
char *cwd = getcwd(buf, sizeof(buf));
- int64_t cwd_len = strlen(cwd);
+ size_t cwd_len = strlen(cwd);
if (strncmp(cwd, filename, cwd_len) == 0 && filename[cwd_len] == '/')
ret->relative_filename = &filename[cwd_len+1];
}
diff --git a/builtins/functions.c b/builtins/functions.c
index 93c4abff..b4e1a5cc 100644
--- a/builtins/functions.c
+++ b/builtins/functions.c
@@ -63,7 +63,8 @@ void print_stack_trace(FILE *out, int start, int stop)
fflush(out);
}
-public void fail(const char *fmt, ...)
+__attribute__((format(printf, 1, 2)))
+public _Noreturn void fail(const char *fmt, ...)
{
fflush(stdout);
if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \n\n\x1b[0;1m", stderr);
@@ -77,9 +78,11 @@ public void fail(const char *fmt, ...)
print_stack_trace(stderr, 2, 4);
fflush(stderr);
raise(SIGABRT);
+ _exit(1);
}
-public void fail_source(const char *filename, int64_t start, int64_t end, const char *fmt, ...)
+__attribute__((format(printf, 4, 5)))
+public _Noreturn void fail_source(const char *filename, int64_t start, int64_t end, const char *fmt, ...)
{
if (USE_COLOR) fputs("\n\x1b[31;7m ==================== ERROR ==================== \n\n\x1b[0;1m", stderr);
else fputs("\n==================== ERROR ====================\n\n", stderr);
@@ -100,9 +103,10 @@ public void fail_source(const char *filename, int64_t start, int64_t end, const
print_stack_trace(stderr, 2, 4);
fflush(stderr);
raise(SIGABRT);
+ _exit(1);
}
-public uint64_t generic_hash(const void *obj, const TypeInfo *type)
+PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo *type)
{
switch (type->tag) {
case TextInfo: return Text$hash((void*)obj);
@@ -114,14 +118,14 @@ public uint64_t generic_hash(const void *obj, const TypeInfo *type)
if (!type->CustomInfo.hash)
goto hash_data;
return type->CustomInfo.hash(obj, type);
- default: {
+ case PointerInfo: case FunctionInfo: case TypeInfoInfo: case OpaqueInfo: default: {
hash_data:;
- return siphash24((void*)obj, type->size);
+ return siphash24((void*)obj, (size_t)(type->size));
}
}
}
-public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type)
+PUREFUNC public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type)
{
if (x == y) return 0;
@@ -136,13 +140,13 @@ public int32_t generic_compare(const void *x, const void *y, const TypeInfo *typ
if (!type->CustomInfo.compare)
goto compare_data;
return type->CustomInfo.compare(x, y, type);
- default:
+ case TypeInfoInfo: case OpaqueInfo: default:
compare_data:
- return (int32_t)memcmp((void*)x, (void*)y, type->size);
+ return (int32_t)memcmp((void*)x, (void*)y, (size_t)(type->size));
}
}
-public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
+PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
{
if (x == y) return true;
@@ -157,7 +161,7 @@ public bool generic_equal(const void *x, const void *y, const TypeInfo *type)
if (!type->CustomInfo.equal)
goto use_generic_compare;
return type->CustomInfo.equal(x, y, type);
- default:
+ case TypeInfoInfo: case OpaqueInfo: default:
use_generic_compare:
return (generic_compare(x, y, type) == 0);
}
@@ -180,6 +184,7 @@ public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo *ty
if (!type->CustomInfo.as_text)
fail("No text function provided for type!\n");
return type->CustomInfo.as_text(obj, colorize, type);
+ case OpaqueInfo: return Text("???");
default: errx(1, "Invalid type tag: %d", type->tag);
}
}
@@ -270,6 +275,11 @@ public Text_t ask(Text_t prompt, bool bold, bool force_tty)
FILE *out = stdout;
FILE *in = stdin;
+ char *line = NULL;
+ size_t bufsize = 0;
+ ssize_t length = 0;
+ char *gc_input = NULL;
+
if (force_tty && !isatty(STDOUT_FILENO)) {
out = fopen("/dev/tty", "w");
if (!out) goto cleanup;
@@ -288,9 +298,7 @@ public Text_t ask(Text_t prompt, bool bold, bool force_tty)
}
}
- char *line = NULL;
- size_t bufsize = 0;
- ssize_t length = getline(&line, &bufsize, in);
+ length = getline(&line, &bufsize, in);
if (length == -1) {
fputs("\n", out); // finish the line, since we didn't get any input
goto cleanup;
@@ -301,10 +309,10 @@ public Text_t ask(Text_t prompt, bool bold, bool force_tty)
--length;
}
- char *gc_input = GC_MALLOC_ATOMIC(length + 1);
- memcpy(gc_input, line, length + 1);
+ gc_input = GC_MALLOC_ATOMIC((size_t)(length + 1));
+ memcpy(gc_input, line, (size_t)(length + 1));
- ret = Text$from_strn(gc_input, length);
+ ret = Text$from_strn(gc_input, (size_t)(length));
cleanup:
if (out && out != stdout) fclose(out);
diff --git a/builtins/functions.h b/builtins/functions.h
index cc1f5a81..f258a20d 100644
--- a/builtins/functions.h
+++ b/builtins/functions.h
@@ -8,10 +8,13 @@
#include "datatypes.h"
#include "types.h"
+#include "util.h"
void tomo_init(void);
-void fail(const char *fmt, ...);
-void fail_source(const char *filename, int64_t start, int64_t end, const char *fmt, ...);
+__attribute__((format(printf, 1, 2)))
+_Noreturn void fail(const char *fmt, ...);
+__attribute__((format(printf, 4, 5)))
+_Noreturn void fail_source(const char *filename, int64_t start, int64_t end, const char *fmt, ...);
Text_t builtin_last_err();
void start_test(const char *filename, int64_t start, int64_t end);
void end_test(const void *expr, const TypeInfo *type, const char *expected, const char *filename, int64_t start, int64_t end);
@@ -22,9 +25,9 @@ void say(Text_t text, bool newline);
Text_t ask(Text_t prompt, bool bold, bool force_tty);
_Noreturn void tomo_exit(Text_t text, int32_t status);
-uint64_t generic_hash(const void *obj, const TypeInfo *type);
-int32_t generic_compare(const void *x, const void *y, const TypeInfo *type);
-bool generic_equal(const void *x, const void *y, const TypeInfo *type);
+PUREFUNC uint64_t generic_hash(const void *obj, const TypeInfo *type);
+PUREFUNC int32_t generic_compare(const void *x, const void *y, const TypeInfo *type);
+PUREFUNC bool generic_equal(const void *x, const void *y, const TypeInfo *type);
Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo *type);
int generic_print(const void *obj, bool colorize, const TypeInfo *type);
closure_t spawn(closure_t fn);
diff --git a/builtins/integers.c b/builtins/integers.c
index 523ec4d1..31e32f3d 100644
--- a/builtins/integers.c
+++ b/builtins/integers.c
@@ -36,29 +36,29 @@ public Text_t Int$as_text(const Int_t *i, bool colorize, const TypeInfo *type) {
}
}
-public int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo *type) {
+public PUREFUNC int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo *type) {
(void)type;
if (__builtin_expect(((x->small | y->small) & 1) == 0, 0))
return x->big == y->big ? 0 : mpz_cmp(*x->big, *y->big);
return (x->small > y->small) - (x->small < y->small);
}
-public int32_t Int$compare_value(const Int_t x, const Int_t y) {
+public PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) {
if (__builtin_expect(((x.small | y.small) & 1) == 0, 0))
return x.big == y.big ? 0 : mpz_cmp(*x.big, *y.big);
return (x.small > y.small) - (x.small < y.small);
}
-public bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo *type) {
+public PUREFUNC bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo *type) {
(void)type;
return x->small == y->small || (__builtin_expect(((x->small | y->small) & 1) == 0, 0) && mpz_cmp(*x->big, *y->big) == 0);
}
-public bool Int$equal_value(const Int_t x, const Int_t y) {
+public PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y) {
return x.small == y.small || (__builtin_expect(((x.small | y.small) & 1) == 0, 0) && mpz_cmp(*x.big, *y.big) == 0);
}
-public uint64_t Int$hash(const Int_t *x, const TypeInfo *type) {
+public PUREFUNC uint64_t Int$hash(const Int_t *x, const TypeInfo *type) {
(void)type;
if (__builtin_expect(x->small & 1, 1)) {
int64_t i = (x->small>>2);
@@ -81,8 +81,8 @@ public Text_t Int$format(Int_t i, Int_t digits_int)
if (needed_zeroes <= 0)
return Text$from_str(str);
- char *zeroes = GC_MALLOC_ATOMIC(needed_zeroes);
- memset(zeroes, '0', needed_zeroes);
+ char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
+ memset(zeroes, '0', (size_t)(needed_zeroes));
if (negative)
return Text$concat(Text("-"), Text$from_str(zeroes), Text$from_str(str + 1));
else
@@ -108,8 +108,8 @@ public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
if (needed_zeroes <= 0)
return prefix ? Text$concat(Text("0x"), Text$from_str(str)) : Text$from_str(str);
- char *zeroes = GC_MALLOC_ATOMIC(needed_zeroes);
- memset(zeroes, '0', needed_zeroes);
+ char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
+ memset(zeroes, '0', (size_t)(needed_zeroes));
if (prefix)
return Text$concat(Text("0x"), Text$from_str(zeroes), Text$from_str(str));
else
@@ -131,8 +131,8 @@ public Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) {
if (needed_zeroes <= 0)
return prefix ? Text$concat(Text("0o"), Text$from_str(str)) : Text$from_str(str);
- char *zeroes = GC_MALLOC_ATOMIC(needed_zeroes);
- memset(zeroes, '0', needed_zeroes);
+ char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
+ memset(zeroes, '0', (size_t)(needed_zeroes));
if (prefix)
return Text$concat(Text("0o"), Text$from_str(zeroes), Text$from_str(str));
else
@@ -302,7 +302,7 @@ public Int_t Int$power(Int_t base, Int_t exponent)
fail("Cannot take a negative power of an integer!");
mpz_t result;
mpz_init_set_int(result, base);
- mpz_pow_ui(result, result, exp);
+ mpz_pow_ui(result, result, (uint64_t)exp);
return Int$from_mpz(result);
}
@@ -339,7 +339,7 @@ public Int_t Int$random(Int_t min, Int_t max) {
return Int$plus(min, Int$from_mpz(r));
}
-public Range_t Int$to(Int_t from, Int_t to) {
+public PUREFUNC Range_t Int$to(Int_t from, Int_t to) {
return (Range_t){from, to, Int$compare_value(to, from) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}};
}
@@ -409,11 +409,11 @@ public const TypeInfo Int$info = {
if (!i) return Text(#KindOfInt); \
return Text$format(colorize ? "\x1b[35m%" fmt "\x1b[m" : "%" fmt, *i); \
} \
- public int32_t KindOfInt ## $compare(const c_type *x, const c_type *y, const TypeInfo *type) { \
+ public PUREFUNC int32_t KindOfInt ## $compare(const c_type *x, const c_type *y, const TypeInfo *type) { \
(void)type; \
return (*x > *y) - (*x < *y); \
} \
- public bool KindOfInt ## $equal(const c_type *x, const c_type *y, const TypeInfo *type) { \
+ public PUREFUNC bool KindOfInt ## $equal(const c_type *x, const c_type *y, const TypeInfo *type) { \
(void)type; \
return *x == *y; \
} \
@@ -458,7 +458,7 @@ public const TypeInfo Int$info = {
public Range_t KindOfInt ## $to(c_type from, c_type to) { \
return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \
} \
- public c_type KindOfInt ## $from_text(Text_t text, bool *success) { \
+ public PUREFUNC c_type KindOfInt ## $from_text(Text_t text, bool *success) { \
bool parsed_int = false; \
Int_t full_int = Int$from_text(text, &parsed_int); \
if (!parsed_int && success) *success = false; \
@@ -482,10 +482,10 @@ public const TypeInfo Int$info = {
.CustomInfo={.compare=(void*)KindOfInt##$compare, .as_text=(void*)KindOfInt##$as_text}, \
};
-DEFINE_INT_TYPE(int64_t, Int64, "ld_i64", INT64_MIN, INT64_MAX);
-DEFINE_INT_TYPE(int32_t, Int32, "d_i32", INT32_MIN, INT32_MAX);
-DEFINE_INT_TYPE(int16_t, Int16, "d_i16", INT16_MIN, INT16_MAX);
-DEFINE_INT_TYPE(int8_t, Int8, "d_i8", INT8_MIN, INT8_MAX);
+DEFINE_INT_TYPE(int64_t, Int64, "ld_i64", INT64_MIN, INT64_MAX)
+DEFINE_INT_TYPE(int32_t, Int32, "d_i32", INT32_MIN, INT32_MAX)
+DEFINE_INT_TYPE(int16_t, Int16, "d_i16", INT16_MIN, INT16_MAX)
+DEFINE_INT_TYPE(int8_t, Int8, "d_i8", INT8_MIN, INT8_MAX)
#undef DEFINE_INT_TYPE
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/integers.h b/builtins/integers.h
index e5765de3..e69914c8 100644
--- a/builtins/integers.h
+++ b/builtins/integers.h
@@ -25,16 +25,16 @@
#define DEFINE_INT_TYPE(c_type, type_name) \
Text_t type_name ## $as_text(const c_type *i, bool colorize, const TypeInfo *type); \
- int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo *type); \
- bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo *type); \
+ PUREFUNC int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo *type); \
+ PUREFUNC bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo *type); \
Text_t type_name ## $format(c_type i, Int_t digits); \
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
Array_t type_name ## $bits(c_type x); \
c_type type_name ## $random(c_type min, c_type max); \
Range_t type_name ## $to(c_type from, c_type to); \
- c_type type_name ## $from_text(Text_t text, bool *success); \
- static inline c_type type_name ## $clamped(c_type x, c_type min, c_type max) { \
+ PUREFUNC c_type type_name ## $from_text(Text_t text, bool *success); \
+ PUREFUNC static inline c_type type_name ## $clamped(c_type x, c_type min, c_type max) { \
return x < min ? min : (x > max ? max : x); \
} \
extern const c_type type_name ## $min, type_name##$max; \
@@ -59,10 +59,10 @@
return type_name ## $modulo(D-1, d) + 1; \
}
-DEFINE_INT_TYPE(int64_t, Int64);
-DEFINE_INT_TYPE(int32_t, Int32);
-DEFINE_INT_TYPE(int16_t, Int16);
-DEFINE_INT_TYPE(int8_t, Int8);
+DEFINE_INT_TYPE(int64_t, Int64)
+DEFINE_INT_TYPE(int32_t, Int32)
+DEFINE_INT_TYPE(int16_t, Int16)
+DEFINE_INT_TYPE(int8_t, Int8)
#undef DEFINE_INT_TYPE
#define Int64$abs(...) I64(labs(__VA_ARGS__))
@@ -71,17 +71,17 @@ DEFINE_INT_TYPE(int8_t, Int8);
#define Int8$abs(...) I8(abs(__VA_ARGS__))
Text_t Int$as_text(const Int_t *i, bool colorize, const TypeInfo *type);
-uint64_t Int$hash(const Int_t *x, const TypeInfo *type);
-int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo *type);
-int32_t Int$compare_value(const Int_t x, const Int_t y);
-bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo *type);
-bool Int$equal_value(const Int_t x, const Int_t y);
+PUREFUNC uint64_t Int$hash(const Int_t *x, const TypeInfo *type);
+PUREFUNC int32_t Int$compare(const Int_t *x, const Int_t *y, const TypeInfo *type);
+PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y);
+PUREFUNC bool Int$equal(const Int_t *x, const Int_t *y, const TypeInfo *type);
+PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y);
Text_t Int$format(Int_t i, Int_t digits);
Text_t Int$hex(Int_t i, Int_t digits, bool uppercase, bool prefix);
Text_t Int$octal(Int_t i, Int_t digits, bool prefix);
void Int$init_random(long seed);
Int_t Int$random(Int_t min, Int_t max);
-Range_t Int$to(Int_t from, Int_t to);
+PUREFUNC Range_t Int$to(Int_t from, Int_t to);
Int_t Int$from_str(const char *str, bool *success);
Int_t Int$from_text(Text_t text, bool *success);
Int_t Int$abs(Int_t x);
@@ -91,20 +91,18 @@ Int_t Int$sqrt(Int_t i);
#define BIGGEST_SMALL_INT ((1<<29)-1)
#define Int$from_mpz(mpz) (\
- mpz_cmpabs_ui(mpz, BIGGEST_SMALL_INT) <= 0 ? ({ \
- (Int_t){.small=(mpz_get_si(mpz)<<2)|1}; \
- }) : ({ \
- mpz_t *result_obj = new(mpz_t); \
- memcpy(result_obj, &mpz, sizeof(mpz_t)); \
- (Int_t){.big=result_obj}; \
- }))
+ mpz_cmpabs_ui(mpz, BIGGEST_SMALL_INT) <= 0 ? ( \
+ (Int_t){.small=(mpz_get_si(mpz)<<2)|1} \
+ ) : ( \
+ (Int_t){.big=memcpy(new(mpz_t), &mpz, sizeof(mpz_t))} \
+ ))
#define mpz_init_set_int(mpz, i) do { \
if (__builtin_expect((i).small & 1, 1)) mpz_init_set_si(mpz, (i).small >> 2); \
else mpz_init_set(mpz, *(i).big); \
} while (0)
-#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int64_to_Int(i))
+#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=(int64_t)((uint64_t)(i)<<2)|1}) : Int64_to_Int(i))
#define I_small(i) ((Int_t){.small=((uint64_t)(i)<<2)|1})
#define I_is_zero(i) ((i).small == 1)
@@ -121,7 +119,6 @@ Int_t Int$slow_bit_or(Int_t x, Int_t y);
Int_t Int$slow_bit_xor(Int_t x, Int_t y);
Int_t Int$slow_negative(Int_t x);
Int_t Int$slow_negated(Int_t x);
-Int_t Int$abs(Int_t x);
bool Int$is_prime(Int_t x, Int_t reps);
Int_t Int$next_prime(Int_t x);
Int_t Int$prev_prime(Int_t x);
@@ -280,7 +277,8 @@ static inline Int_t Int64_to_Int(int64_t i)
#define Int16_to_Int(i) Int64_to_Int(i)
#define Int8_to_Int(i) Int64_to_Int(i)
-static inline Int64_t Int_to_Int64(Int_t i, bool truncate) {
+#pragma GCC diagnostic ignored "-Winline"
+PUREFUNC static inline Int64_t Int_to_Int64(Int_t i, bool truncate) {
if (__builtin_expect(i.small & 1, 1))
return (int64_t)(i.small >> 2);
if (__builtin_expect(!truncate && !mpz_fits_slong_p(*i.big), 0))
@@ -288,7 +286,7 @@ static inline Int64_t Int_to_Int64(Int_t i, bool truncate) {
return mpz_get_si(*i.big);
}
-static inline Int32_t Int_to_Int32(Int_t i, bool truncate) {
+PUREFUNC static inline Int32_t Int_to_Int32(Int_t i, bool truncate) {
int64_t i64 = Int_to_Int64(i, truncate);
int32_t i32 = (int32_t)i64;
if (__builtin_expect(i64 != i32 && !truncate, 0))
@@ -296,7 +294,7 @@ static inline Int32_t Int_to_Int32(Int_t i, bool truncate) {
return i32;
}
-static inline Int16_t Int_to_Int16(Int_t i, bool truncate) {
+PUREFUNC static inline Int16_t Int_to_Int16(Int_t i, bool truncate) {
int64_t i64 = Int_to_Int64(i, truncate);
int16_t i16 = (int16_t)i64;
if (__builtin_expect(i64 != i16 && !truncate, 0))
@@ -304,7 +302,7 @@ static inline Int16_t Int_to_Int16(Int_t i, bool truncate) {
return i16;
}
-static inline Int8_t Int_to_Int8(Int_t i, bool truncate) {
+PUREFUNC static inline Int8_t Int_to_Int8(Int_t i, bool truncate) {
int64_t i64 = Int_to_Int64(i, truncate);
int8_t i8 = (int8_t)i64;
if (__builtin_expect(i64 != i8 && !truncate, 0))
@@ -312,14 +310,14 @@ static inline Int8_t Int_to_Int8(Int_t i, bool truncate) {
return i8;
}
-static inline Int_t Num_to_Int(double n)
+PUREFUNC static inline Int_t Num_to_Int(double n)
{
mpz_t result;
mpz_init_set_d(result, n);
return Int$from_mpz(result);
}
-static inline double Int_to_Num(Int_t i)
+PUREFUNC static inline double Int_to_Num(Int_t i)
{
if (__builtin_expect(i.small & 1, 1))
return (double)(i.small >> 2);
@@ -330,7 +328,7 @@ static inline double Int_to_Num(Int_t i)
#define Int_to_Num32(i) (Num32_t)Int_to_Num(i)
#define CONVERSION_FUNC(hi, lo) \
- static inline int##lo##_t Int##hi##_to_Int##lo(int##hi##_t i, bool truncate) { \
+ PUREFUNC static inline int##lo##_t Int##hi##_to_Int##lo(int##hi##_t i, bool truncate) { \
if (__builtin_expect(!truncate && (i != (int##lo##_t)i), 0)) \
fail("Cannot truncate the Int" #hi " %ld to an Int" #lo, (int64_t)i); \
return (int##lo##_t)i; \
@@ -344,11 +342,12 @@ CONVERSION_FUNC(32, 8)
CONVERSION_FUNC(16, 8)
#undef CONVERSION_FUNC
+#pragma GCC diagnostic ignored "-Wfloat-equal"
#define CONVERSION_FUNC(num, int_type) \
- static inline int_type##_t num##_to_##int_type(num##_t n, bool truncate) { \
- num##_t rounded = round(n); \
+ PUREFUNC static inline int_type##_t num##_to_##int_type(num##_t n, bool truncate) { \
+ num##_t rounded = (num##_t)round((double)n); \
if (__builtin_expect(!truncate && (num##_t)(int_type##_t)rounded != rounded, 0)) \
- fail("Cannot truncate the " #num " %g to an " #int_type, rounded); \
+ fail("Cannot truncate the " #num " %g to an " #int_type, (double)rounded); \
return (int_type##_t)rounded; \
}
diff --git a/builtins/nums.c b/builtins/nums.c
index 35ec9b18..90eb75ce 100644
--- a/builtins/nums.c
+++ b/builtins/nums.c
@@ -14,23 +14,23 @@
#include "text.h"
#include "types.h"
-public Text_t Num$as_text(const double *f, bool colorize, const TypeInfo *type) {
+public PUREFUNC Text_t Num$as_text(const double *f, bool colorize, const TypeInfo *type) {
(void)type;
if (!f) return Text("Num");
return Text$format(colorize ? "\x1b[35m%.16g\x1b[33;2m\x1b[m" : "%.16g", *f);
}
-public int32_t Num$compare(const double *x, const double *y, const TypeInfo *type) {
+public PUREFUNC int32_t Num$compare(const double *x, const double *y, const TypeInfo *type) {
(void)type;
return (*x > *y) - (*x < *y);
}
-public bool Num$equal(const double *x, const double *y, const TypeInfo *type) {
+public PUREFUNC bool Num$equal(const double *x, const double *y, const TypeInfo *type) {
(void)type;
return *x == *y;
}
-public bool Num$near(double a, double b, double ratio, double absolute) {
+public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) {
if (ratio < 0) ratio = 0;
else if (ratio > 1) ratio = 1;
@@ -62,7 +62,7 @@ public double Num$random(void) {
return drand48();
}
-public double Num$mix(double amount, double x, double y) {
+public CONSTFUNC double Num$mix(double amount, double x, double y) {
return (1.0-amount)*x + amount*y;
}
@@ -78,9 +78,9 @@ public double Num$nan(Text_t tag) {
return nan(Text$as_c_string(tag));
}
-public bool Num$isinf(double n) { return !!isinf(n); }
-public bool Num$finite(double n) { return !!finite(n); }
-public bool Num$isnan(double n) { return !!isnan(n); }
+public CONSTFUNC bool Num$isinf(double n) { return !!isinf(n); }
+public CONSTFUNC bool Num$finite(double n) { return !!finite(n); }
+public CONSTFUNC bool Num$isnan(double n) { return !!isnan(n); }
public const TypeInfo Num$info = {
.size=sizeof(double),
@@ -93,23 +93,23 @@ public const TypeInfo Num$info = {
},
};
-public Text_t Num32$as_text(const float *f, bool colorize, const TypeInfo *type) {
+public PUREFUNC Text_t Num32$as_text(const float *f, bool colorize, const TypeInfo *type) {
(void)type;
if (!f) return Text("Num32");
- return Text$format(colorize ? "\x1b[35m%.8g_f32\x1b[33;2m\x1b[m" : "%.8g_f32", *f);
+ return Text$format(colorize ? "\x1b[35m%.8g_f32\x1b[33;2m\x1b[m" : "%.8g_f32", (double)*f);
}
-public int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type) {
+public PUREFUNC int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type) {
(void)type;
return (*x > *y) - (*x < *y);
}
-public bool Num32$equal(const float *x, const float *y, const TypeInfo *type) {
+public PUREFUNC bool Num32$equal(const float *x, const float *y, const TypeInfo *type) {
(void)type;
return *x == *y;
}
-public bool Num32$near(float a, float b, float ratio, float absolute) {
+public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) {
if (ratio < 0) ratio = 0;
else if (ratio > 1) ratio = 1;
@@ -125,11 +125,11 @@ public bool Num32$near(float a, float b, float ratio, float absolute) {
}
public Text_t Num32$format(float f, Int_t precision) {
- return Text$format("%.*f", (int)Int_to_Int64(precision, false), f);
+ return Text$format("%.*f", (int)Int_to_Int64(precision, false), (double)f);
}
public Text_t Num32$scientific(float f, Int_t precision) {
- return Text$format("%.*e", (int)Int_to_Int64(precision, false), f);
+ return Text$format("%.*e", (int)Int_to_Int64(precision, false), (double)f);
}
public float Num32$mod(float num, float modulus) {
@@ -141,8 +141,8 @@ public float Num32$random(void) {
return (float)drand48();
}
-public float Num32$mix(float amount, float x, float y) {
- return (1.0-amount)*x + amount*y;
+public CONSTFUNC float Num32$mix(float amount, float x, float y) {
+ return (1.0f-amount)*x + amount*y;
}
public float Num32$from_text(Text_t text, bool *success) {
@@ -157,9 +157,9 @@ public float Num32$nan(Text_t tag) {
return nanf(Text$as_c_string(tag));
}
-public bool Num32$isinf(float n) { return isinf(n); }
-public bool Num32$finite(float n) { return finite(n); }
-public bool Num32$isnan(float n) { return isnan(n); }
+public CONSTFUNC bool Num32$isinf(float n) { return isinf(n); }
+public CONSTFUNC bool Num32$finite(float n) { return finite(n); }
+public CONSTFUNC bool Num32$isnan(float n) { return isnan(n); }
public const TypeInfo Num32$info = {
.size=sizeof(float),
diff --git a/builtins/nums.h b/builtins/nums.h
index 059ac7bd..4205274b 100644
--- a/builtins/nums.h
+++ b/builtins/nums.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "types.h"
+#include "util.h"
#define Num_t double
#define Num32_t float
@@ -15,39 +16,39 @@
#define N64(n) ((double)n)
Text_t Num$as_text(const double *f, bool colorize, const TypeInfo *type);
-int32_t Num$compare(const double *x, const double *y, const TypeInfo *type);
-bool Num$equal(const double *x, const double *y, const TypeInfo *type);
-bool Num$near(double a, double b, double ratio, double absolute);
+PUREFUNC int32_t Num$compare(const double *x, const double *y, const TypeInfo *type);
+PUREFUNC bool Num$equal(const double *x, const double *y, const TypeInfo *type);
+CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute);
Text_t Num$format(double f, Int_t precision);
Text_t Num$scientific(double f, Int_t precision);
double Num$mod(double num, double modulus);
-bool Num$isinf(double n);
-bool Num$finite(double n);
-bool Num$isnan(double n);
+CONSTFUNC bool Num$isinf(double n);
+CONSTFUNC bool Num$finite(double n);
+CONSTFUNC bool Num$isnan(double n);
double Num$nan(Text_t tag);
double Num$random(void);
-double Num$mix(double amount, double x, double y);
+CONSTFUNC double Num$mix(double amount, double x, double y);
double Num$from_text(Text_t text, bool *success);
-static inline double Num$clamped(double x, double low, double high) {
+CONSTFUNC static inline double Num$clamped(double x, double low, double high) {
return (x <= low) ? low : (x >= high ? high : x);
}
extern const TypeInfo Num$info;
Text_t Num32$as_text(const float *f, bool colorize, const TypeInfo *type);
-int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type);
-bool Num32$equal(const float *x, const float *y, const TypeInfo *type);
-bool Num32$near(float a, float b, float ratio, float absolute);
+PUREFUNC int32_t Num32$compare(const float *x, const float *y, const TypeInfo *type);
+PUREFUNC bool Num32$equal(const float *x, const float *y, const TypeInfo *type);
+CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute);
Text_t Num32$format(float f, Int_t precision);
Text_t Num32$scientific(float f, Int_t precision);
float Num32$mod(float num, float modulus);
-bool Num32$isinf(float n);
-bool Num32$finite(float n);
-bool Num32$isnan(float n);
+CONSTFUNC bool Num32$isinf(float n);
+CONSTFUNC bool Num32$finite(float n);
+CONSTFUNC bool Num32$isnan(float n);
float Num32$random(void);
-float Num32$mix(float amount, float x, float y);
+CONSTFUNC float Num32$mix(float amount, float x, float y);
float Num32$from_text(Text_t text, bool *success);
float Num32$nan(Text_t tag);
-static inline float Num32$clamped(float x, float low, float high) {
+CONSTFUNC static inline float Num32$clamped(float x, float low, float high) {
return (x <= low) ? low : (x >= high ? high : x);
}
extern const TypeInfo Num32$info;
diff --git a/builtins/pointer.c b/builtins/pointer.c
index 66cd308a..0d89e8a6 100644
--- a/builtins/pointer.c
+++ b/builtins/pointer.c
@@ -79,13 +79,13 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo *type
return text;
}
-public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type) {
+PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type) {
(void)type;
const void *xp = *(const void**)x, *yp = *(const void**)y;
return (xp > yp) - (xp < yp);
}
-public bool Pointer$equal(const void *x, const void *y, const TypeInfo *type) {
+PUREFUNC public bool Pointer$equal(const void *x, const void *y, const TypeInfo *type) {
(void)type;
const void *xp = *(const void**)x, *yp = *(const void**)y;
return xp == yp;
diff --git a/builtins/pointer.h b/builtins/pointer.h
index 7748da4b..c3c622cf 100644
--- a/builtins/pointer.h
+++ b/builtins/pointer.h
@@ -7,10 +7,11 @@
#include <stdint.h>
#include "types.h"
+#include "util.h"
Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo *type);
-int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type);
-bool Pointer$equal(const void *x, const void *y, const TypeInfo *type);
+PUREFUNC int32_t Pointer$compare(const void *x, const void *y, const TypeInfo *type);
+PUREFUNC bool Pointer$equal(const void *x, const void *y, const TypeInfo *type);
#define Null(t) (t*)NULL
#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo){\
diff --git a/builtins/range.c b/builtins/range.c
index 1c8106eb..9dfd1efe 100644
--- a/builtins/range.c
+++ b/builtins/range.c
@@ -15,7 +15,7 @@
#include "util.h"
-static int32_t Range$compare(const Range_t *x, const Range_t *y, const TypeInfo *type)
+PUREFUNC static int32_t Range$compare(const Range_t *x, const Range_t *y, const TypeInfo *type)
{
(void)type;
if (x == y) return 0;
@@ -26,7 +26,7 @@ static int32_t Range$compare(const Range_t *x, const Range_t *y, const TypeInfo
return Int$compare(&x->step, &y->step, &Int$info);
}
-static bool Range$equal(const Range_t *x, const Range_t *y, const TypeInfo *type)
+PUREFUNC static bool Range$equal(const Range_t *x, const Range_t *y, const TypeInfo *type)
{
(void)type;
if (x == y) return true;
@@ -44,12 +44,12 @@ static Text_t Range$as_text(const Range_t *r, bool use_color, const TypeInfo *ty
Int$as_text(&r->step, use_color, &Int$info));
}
-public Range_t Range$reversed(Range_t r)
+PUREFUNC public Range_t Range$reversed(Range_t r)
{
return (Range_t){r.last, r.first, Int$negative(r.step)};
}
-public Range_t Range$by(Range_t r, Int_t step)
+PUREFUNC public Range_t Range$by(Range_t r, Int_t step)
{
return (Range_t){r.first, r.last, Int$times(step, r.step)};
}
diff --git a/builtins/range.h b/builtins/range.h
index 802c85f8..2a4f1d68 100644
--- a/builtins/range.h
+++ b/builtins/range.h
@@ -2,8 +2,8 @@
// Ranges represent numeric ranges
-Range_t Range$reversed(Range_t r);
-Range_t Range$by(Range_t r, Int_t step);
+PUREFUNC Range_t Range$reversed(Range_t r);
+PUREFUNC Range_t Range$by(Range_t r, Int_t step);
extern const TypeInfo Range;
diff --git a/builtins/shell.c b/builtins/shell.c
index da6cbe5b..91cf792f 100644
--- a/builtins/shell.c
+++ b/builtins/shell.c
@@ -25,7 +25,7 @@ public Pattern_t Shell$escape_text(Text_t text)
add_char('"');
add_char('\'');
} else
- add_char(*p);
+ add_char((uint8_t)*p);
}
add_char('\'');
#undef add_char
diff --git a/builtins/siphash-internals.h b/builtins/siphash-internals.h
index 95b00b53..4a0dc7cf 100644
--- a/builtins/siphash-internals.h
+++ b/builtins/siphash-internals.h
@@ -83,6 +83,7 @@ static inline void siphashadd64bits (siphash *sh, const uint64_t in) {
DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
sh->v0 ^= mi;
}
+#pragma GCC diagnostic ignored "-Winline"
static inline uint64_t siphashfinish_last_part (siphash *sh, uint64_t t) {
sh->b |= t;
sh->v3 ^= sh->b;
@@ -118,6 +119,7 @@ static inline uint64_t siphashfinish (siphash *sh, const uint8_t *src, size_t sr
case 2: t.u8[1] = src[1];
/* Falls through */
case 1: t.u8[0] = src[0];
+ default: break;
}
return siphashfinish_last_part(sh, t.u64);
}
diff --git a/builtins/siphash.c b/builtins/siphash.c
index add2a747..35c882ca 100644
--- a/builtins/siphash.c
+++ b/builtins/siphash.c
@@ -46,12 +46,13 @@
public uint64_t siphash24(const uint8_t *src, size_t src_sz) {
siphash sh;
if ((uint64_t)src % __alignof__(uint64_t) == 0) {
+#pragma GCC diagnostic ignored "-Wcast-align"
const uint64_t *in = (uint64_t*)src;
/* Find largest src_sz evenly divisible by 8 bytes. */
- const ptrdiff_t src_sz_nearest_8bits = (src_sz >> 3) << 3;
+ const ptrdiff_t src_sz_nearest_8bits = ((ptrdiff_t)src_sz >> 3) << 3;
const uint64_t *goal = (uint64_t*)(src + src_sz_nearest_8bits);
siphashinit(&sh, src_sz);
- src_sz -= src_sz_nearest_8bits;
+ src_sz -= (size_t)src_sz_nearest_8bits;
while (in < goal) {
siphashadd64bits(&sh, *in);
in++;
diff --git a/builtins/table.c b/builtins/table.c
index a5dafd48..cd87c897 100644
--- a/builtins/table.c
+++ b/builtins/table.c
@@ -40,7 +40,6 @@
#define END_OF_CHAIN UINT32_MAX
#define GET_ENTRY(t, i) ((t).entries.data + (t).entries.stride*(i))
-#define ENTRIES_TYPE(type) (&(TypeInfo){.size=sizeof(Array_t), .align=__alignof__(Array_t), .tag=ArrayInfo, .ArrayInfo.item=(&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo})})
static const TypeInfo MemoryPointer = {
.size=sizeof(void*),
@@ -59,27 +58,27 @@ const TypeInfo CStrToVoidStarTable = {
.TableInfo={.key=&CString$info, .value=&MemoryPointer},
};
-static inline size_t entry_size(const TypeInfo *info)
+PUREFUNC static inline size_t entry_size(const TypeInfo *info)
{
- size_t size = info->TableInfo.key->size;
- if (info->TableInfo.value->align > 1 && size % info->TableInfo.value->align)
- size += info->TableInfo.value->align - (size % info->TableInfo.value->align); // padding
- size += info->TableInfo.value->size;
- if (info->TableInfo.key->align > 1 && size % info->TableInfo.key->align)
- size += info->TableInfo.key->align - (size % info->TableInfo.key->align); // padding
+ size_t size = (size_t)info->TableInfo.key->size;
+ if (info->TableInfo.value->align > 1 && size % (size_t)info->TableInfo.value->align)
+ size += (size_t)info->TableInfo.value->align - (size % (size_t)info->TableInfo.value->align); // padding
+ size += (size_t)info->TableInfo.value->size;
+ if (info->TableInfo.key->align > 1 && size % (size_t)info->TableInfo.key->align)
+ size += (size_t)info->TableInfo.key->align - (size % (size_t)info->TableInfo.key->align); // padding
return size;
}
-static inline size_t entry_align(const TypeInfo *info)
+PUREFUNC static inline size_t entry_align(const TypeInfo *info)
{
- return MAX(info->TableInfo.key->align, info->TableInfo.value->align);
+ return (size_t)MAX(info->TableInfo.key->align, info->TableInfo.value->align);
}
-static inline size_t value_offset(const TypeInfo *info)
+PUREFUNC static inline size_t value_offset(const TypeInfo *info)
{
- size_t offset = info->TableInfo.key->size;
- if (info->TableInfo.value->align > 1 && offset % info->TableInfo.value->align)
- offset += info->TableInfo.value->align - (offset % info->TableInfo.value->align); // padding
+ size_t offset = (size_t)info->TableInfo.key->size;
+ if ((size_t)info->TableInfo.value->align > 1 && offset % (size_t)info->TableInfo.value->align)
+ offset += (size_t)info->TableInfo.value->align - (offset % (size_t)info->TableInfo.value->align); // padding
return offset;
}
@@ -99,17 +98,17 @@ static inline void hshow(const Table_t *t)
static void maybe_copy_on_write(Table_t *t, const TypeInfo *type)
{
if (t->entries.data_refcount != 0)
- Array$compact(&t->entries, entry_size(type));
+ Array$compact(&t->entries, (int64_t)entry_size(type));
if (t->bucket_info && t->bucket_info->data_refcount != 0) {
- int64_t size = sizeof(bucket_info_t) + sizeof(bucket_t[t->bucket_info->count]);
+ size_t size = sizeof(bucket_info_t) + sizeof(bucket_t[t->bucket_info->count]);
t->bucket_info = memcpy(GC_MALLOC(size), t->bucket_info, size);
t->bucket_info->data_refcount = 0;
}
}
// Return address of value or NULL
-public void *Table$get_raw(Table_t t, const void *key, const TypeInfo *type)
+PUREFUNC public void *Table$get_raw(Table_t t, const void *key, const TypeInfo *type)
{
assert(type->tag == TableInfo);
if (!key || !t.bucket_info) return NULL;
@@ -131,7 +130,7 @@ public void *Table$get_raw(Table_t t, const void *key, const TypeInfo *type)
return NULL;
}
-public void *Table$get(Table_t t, const void *key, const TypeInfo *type)
+PUREFUNC public void *Table$get(Table_t t, const void *key, const TypeInfo *type)
{
assert(type->tag == TableInfo);
for (const Table_t *iter = &t; iter; iter = iter->fallback) {
@@ -201,7 +200,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
fail("Table has exceeded the maximum table size (2^31) and cannot grow further!");
hdebug("About to resize from %u to %u\n", t->bucket_info ? t->bucket_info->count : 0, new_capacity);
hshow(t);
- int64_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[new_capacity]);
+ size_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[new_capacity]);
t->bucket_info = GC_MALLOC_ATOMIC(alloc_size);
memset(t->bucket_info->buckets, 0, sizeof(bucket_t[new_capacity]));
t->bucket_info->count = new_capacity;
@@ -217,6 +216,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
}
// Return address of value
+#pragma GCC diagnostic ignored "-Wstack-protector"
public void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeInfo *type)
{
assert(type->tag == TableInfo);
@@ -237,7 +237,7 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
value_home = t->entries.data + offset;
if (value && value_size > 0)
- memcpy(value_home, value, value_size);
+ memcpy(value_home, value, (size_t)value_size);
return value_home;
}
@@ -246,7 +246,7 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
// Resize buckets if necessary
if (t->entries.length >= (int64_t)t->bucket_info->count) {
- uint32_t newsize = t->bucket_info->count + MIN(t->bucket_info->count, 64);
+ uint32_t newsize = (uint32_t)t->bucket_info->count + MIN((uint32_t)t->bucket_info->count, 64);
if (__builtin_expect(newsize > TABLE_MAX_BUCKETS, 0))
newsize = t->entries.length + 1;
hashmap_resize_buckets(t, newsize, type);
@@ -263,12 +263,12 @@ public void *Table$reserve(Table_t *t, const void *key, const void *value, const
char buf[entry_size(type)];
memset(buf, 0, sizeof(buf));
- memcpy(buf, key, key_size);
+ memcpy(buf, key, (size_t)key_size);
if (value && value_size > 0)
- memcpy(buf + value_offset(type), value, value_size);
+ memcpy(buf + value_offset(type), value, (size_t)value_size);
else
- memset(buf + value_offset(type), 0, value_size);
- Array$insert(&t->entries, buf, I(0), entry_size(type));
+ memset(buf + value_offset(type), 0, (size_t)value_size);
+ Array$insert(&t->entries, buf, I(0), (int64_t)entry_size(type));
int64_t entry_index = t->entries.length-1;
void *entry = GET_ENTRY(*t, entry_index);
@@ -351,7 +351,7 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo *type)
// Last entry is being removed, so clear it out to be safe:
memset(GET_ENTRY(*t, last_entry), 0, entry_size(type));
- Array$remove_at(&t->entries, I(t->entries.length), I(1), entry_size(type));
+ Array$remove_at(&t->entries, I(t->entries.length), I(1), (int64_t)entry_size(type));
int64_t bucket_to_clear;
if (prev) { // Middle (or end) of a chain
@@ -374,7 +374,7 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo *type)
hshow(t);
}
-public void *Table$entry(Table_t t, int64_t n)
+CONSTFUNC public void *Table$entry(Table_t t, int64_t n)
{
if (n < 1 || n > Table$length(t))
return NULL;
@@ -389,11 +389,11 @@ public void Table$clear(Table_t *t)
public Table_t Table$sorted(Table_t t, const TypeInfo *type)
{
closure_t cmp = (closure_t){.fn=generic_compare, .userdata=(void*)type->TableInfo.key};
- Array_t entries = Array$sorted(t.entries, cmp, entry_size(type));
+ Array_t entries = Array$sorted(t.entries, cmp, (int64_t)entry_size(type));
return Table$from_entries(entries, type);
}
-public bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo *type)
+PUREFUNC public bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo *type)
{
if (x == y) return true;
@@ -407,7 +407,7 @@ public bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo *type
return (Table$compare(x, y, type) == 0);
}
-public int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo *type)
+PUREFUNC public int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo *type)
{
if (x == y) return 0;
@@ -438,7 +438,7 @@ public int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo
return 0;
}
-public uint64_t Table$hash(const Table_t *t, const TypeInfo *type)
+PUREFUNC public uint64_t Table$hash(const Table_t *t, const TypeInfo *type)
{
assert(type->tag == TableInfo);
// Table hashes are computed as:
@@ -473,7 +473,7 @@ public Text_t Table$as_text(const Table_t *t, bool colorize, const TypeInfo *typ
Text("}"));
}
- int64_t val_off = value_offset(type);
+ int64_t val_off = (int64_t)value_offset(type);
Text_t text = Text("{");
for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
if (i > 0)
@@ -500,13 +500,13 @@ public Table_t Table$from_entries(Array_t entries, const TypeInfo *type)
Table_t t = {};
int64_t length = entries.length + entries.length / 4;
- int64_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[length]);
+ size_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[length]);
t.bucket_info = GC_MALLOC_ATOMIC(alloc_size);
memset(t.bucket_info->buckets, 0, sizeof(bucket_t[length]));
t.bucket_info->count = length;
t.bucket_info->last_free = length-1;
- int64_t offset = value_offset(type);
+ size_t offset = value_offset(type);
for (int64_t i = 0; i < entries.length; i++) {
void *key = entries.data + i*entries.stride;
Table$set(&t, key, key + offset, type);
@@ -583,7 +583,7 @@ public Table_t Table$without(Table_t a, Table_t b, const TypeInfo *type)
return result;
}
-public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type)
+PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type)
{
if (a.entries.length > b.entries.length || (strict && a.entries.length == b.entries.length))
return false;
@@ -595,18 +595,18 @@ public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo
return true;
}
-public bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type)
+PUREFUNC public bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type)
{
return Table$is_subset_of(b, a, strict, type);
}
-public void *Table$str_get(Table_t t, const char *key)
+PUREFUNC public void *Table$str_get(Table_t t, const char *key)
{
void **ret = Table$get(t, &key, &CStrToVoidStarTable);
return ret ? *ret : NULL;
}
-public void *Table$str_get_raw(Table_t t, const char *key)
+PUREFUNC public void *Table$str_get_raw(Table_t t, const char *key)
{
void **ret = Table$get_raw(t, &key, &CStrToVoidStarTable);
return ret ? *ret : NULL;
@@ -627,7 +627,7 @@ public void Table$str_remove(Table_t *t, const char *key)
return Table$remove(t, &key, &CStrToVoidStarTable);
}
-public void *Table$str_entry(Table_t t, int64_t n)
+CONSTFUNC public void *Table$str_entry(Table_t t, int64_t n)
{
return Table$entry(t, n);
}
diff --git a/builtins/table.h b/builtins/table.h
index 91e87bc5..8e6e5de1 100644
--- a/builtins/table.h
+++ b/builtins/table.h
@@ -44,8 +44,8 @@ void *Table$get(Table_t t, const void *key, const TypeInfo *type);
#define Table$has_value(table_expr, key_expr, info_expr) ({ \
const Table_t t = table_expr; __typeof(key_expr) k = key_expr; \
(Table$get(t, &k, info_expr) != NULL); })
-void *Table$get_raw(Table_t t, const void *key, const TypeInfo *type);
-void *Table$entry(Table_t t, int64_t n);
+PUREFUNC void *Table$get_raw(Table_t t, const void *key, const TypeInfo *type);
+CONSTFUNC void *Table$entry(Table_t t, int64_t n);
void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeInfo *type);
void Table$set(Table_t *t, const void *key, const void *value, const TypeInfo *type);
#define Table$set_value(t, key_expr, value_expr, type) ({ __typeof(key_expr) k = key_expr; __typeof(value_expr) v = value_expr; \
@@ -63,22 +63,22 @@ void Table$remove(Table_t *t, const void *key, const TypeInfo *type);
Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo *type);
Table_t Table$with(Table_t a, Table_t b, const TypeInfo *type);
Table_t Table$without(Table_t a, Table_t b, const TypeInfo *type);
-bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type);
-bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type);
+PUREFUNC bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type);
+PUREFUNC bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo *type);
void Table$clear(Table_t *t);
Table_t Table$sorted(Table_t t, const TypeInfo *type);
void Table$mark_copy_on_write(Table_t *t);
#define TABLE_INCREF(t) ({ ARRAY_INCREF((t).entries); if ((t).bucket_info) (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); })
#define TABLE_COPY(t) ({ TABLE_INCREF(t); t; })
-int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo *type);
-bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo *type);
-uint64_t Table$hash(const Table_t *t, const TypeInfo *type);
+PUREFUNC int32_t Table$compare(const Table_t *x, const Table_t *y, const TypeInfo *type);
+PUREFUNC bool Table$equal(const Table_t *x, const Table_t *y, const TypeInfo *type);
+PUREFUNC uint64_t Table$hash(const Table_t *t, const TypeInfo *type);
Text_t Table$as_text(const Table_t *t, bool colorize, const TypeInfo *type);
-void *Table$str_entry(Table_t t, int64_t n);
-void *Table$str_get(Table_t t, const char *key);
-void *Table$str_get_raw(Table_t t, const char *key);
+CONSTFUNC void *Table$str_entry(Table_t t, int64_t n);
+PUREFUNC void *Table$str_get(Table_t t, const char *key);
+PUREFUNC void *Table$str_get_raw(Table_t t, const char *key);
void Table$str_set(Table_t *t, const char *key, const void *value);
void *Table$str_reserve(Table_t *t, const char *key, const void *value);
void Table$str_remove(Table_t *t, const char *key);
diff --git a/builtins/text.c b/builtins/text.c
index db62b848..c9244fa4 100644
--- a/builtins/text.c
+++ b/builtins/text.c
@@ -45,7 +45,7 @@
// AKA: LATIN CAPITAL LETTER H, LATIN SMALL LETTER E, COMBINING VERTICAL LINE BELOW
// This would be stored as: (int32_t[]){0x48, -2}
// Where -2 is used as a lookup in an array that holds the actual unicode codepoints:
-// (uint32_t[]){0x65, 0x0309}
+// (ucs4_t[]){0x65, 0x0309}
#include <assert.h>
#include <ctype.h>
@@ -79,8 +79,8 @@
#include "siphash-internals.h"
typedef struct {
- uint32_t main_codepoint;
- uint32_t *utf32_cluster; // length-prefixed
+ ucs4_t main_codepoint;
+ ucs4_t *utf32_cluster; // length-prefixed
const uint8_t *utf8;
} synthetic_grapheme_t;
@@ -91,37 +91,38 @@ typedef struct {
#define MAX_BACKREFS 100
// Synthetic grapheme clusters (clusters of more than one codepoint):
-static Table_t grapheme_ids_by_codepoints = {}; // uint32_t* length-prefixed codepoints -> int32_t ID
+static Table_t grapheme_ids_by_codepoints = {}; // ucs4_t* length-prefixed codepoints -> int32_t ID
// This will hold a dynamically growing array of synthetic graphemes:
static synthetic_grapheme_t *synthetic_graphemes = NULL;
static int32_t synthetic_grapheme_capacity = 0;
static int32_t num_synthetic_graphemes = 0;
-#define MAIN_GRAPHEME_CODEPOINT(g) ((g) >= 0 ? (uint32_t)(g) : synthetic_graphemes[-(g)-1].main_codepoint)
+#define MAIN_GRAPHEME_CODEPOINT(_g) ({ int32_t g = _g; (g) >= 0 ? (ucs4_t)(g) : synthetic_graphemes[-(g)-1].main_codepoint; })
#define NUM_GRAPHEME_CODEPOINTS(id) (synthetic_graphemes[-(id)-1].utf32_cluster[0])
#define GRAPHEME_CODEPOINTS(id) (&synthetic_graphemes[-(id)-1].utf32_cluster[1])
#define GRAPHEME_UTF8(id) (synthetic_graphemes[-(id)-1].utf8)
static int32_t get_grapheme(Text_t text, int64_t index);
-static int32_t _next_grapheme(Text_t text, text_iter_t *state, int64_t index);
-static Text_t text_from_u32(uint32_t *codepoints, int64_t num_codepoints, bool normalize);
+static int32_t _get_grapheme(Text_t text, text_iter_t *state, int64_t index);
+#define _get_main_grapheme(...) MAIN_GRAPHEME_CODEPOINT(_get_grapheme(__VA_ARGS__))
+static Text_t text_from_u32(ucs4_t *codepoints, int64_t num_codepoints, bool normalize);
-static bool graphemes_equal(uint32_t **a, uint32_t **b) {
+PUREFUNC static bool graphemes_equal(ucs4_t **a, ucs4_t **b) {
if ((*a)[0] != (*b)[0]) return false;
for (int i = 0; i < (int)(*a)[0]; i++)
if ((*a)[i] != (*b)[i]) return false;
return true;
}
-static uint64_t grapheme_hash(uint32_t **g) {
- uint32_t *cluster = *g;
- return siphash24((void*)&cluster[1], sizeof(uint32_t[cluster[0]]));
+PUREFUNC static uint64_t grapheme_hash(ucs4_t **g) {
+ ucs4_t *cluster = *g;
+ return siphash24((void*)&cluster[1], sizeof(ucs4_t[cluster[0]]));
}
static const TypeInfo GraphemeClusterInfo = {
- .size=sizeof(uint32_t*),
- .align=__alignof__(uint32_t*),
+ .size=sizeof(ucs4_t*),
+ .align=__alignof__(ucs4_t*),
.tag=CustomInfo,
.CustomInfo={.equal=(void*)graphemes_equal, .hash=(void*)grapheme_hash},
};
@@ -131,13 +132,14 @@ static const TypeInfo GraphemeIDLookupTableInfo = {
.tag=TableInfo, .TableInfo={.key=&GraphemeClusterInfo, .value=&Int32$info},
};
-int32_t get_synthetic_grapheme(const uint32_t *codepoints, int64_t utf32_len)
+#pragma GCC diagnostic ignored "-Wstack-protector"
+int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_len)
{
- uint32_t length_prefixed[1+utf32_len] = {};
- length_prefixed[0] = (uint32_t)utf32_len;
+ ucs4_t length_prefixed[1+utf32_len] = {};
+ length_prefixed[0] = (ucs4_t)utf32_len;
for (int i = 0; i < utf32_len; i++)
length_prefixed[i+1] = codepoints[i];
- uint32_t *ptr = &length_prefixed[0];
+ ucs4_t *ptr = &length_prefixed[0];
// Optimization for common case of one frequently used synthetic grapheme:
static int32_t last_grapheme = 0;
@@ -162,18 +164,18 @@ int32_t get_synthetic_grapheme(const uint32_t *codepoints, int64_t utf32_len)
// Get UTF8 representation:
uint8_t u8_buf[64];
size_t u8_len = sizeof(u8_buf)/sizeof(u8_buf[0]);
- uint8_t *u8 = u32_to_u8(codepoints, utf32_len, u8_buf, &u8_len);
+ uint8_t *u8 = u32_to_u8(codepoints, (size_t)utf32_len, u8_buf, &u8_len);
// For performance reasons, use an arena allocator here to ensure that
// synthetic graphemes store all of their information in a densely packed
// area with good cache locality:
static void *arena = NULL, *arena_end = NULL;
// Eat up any space needed to make arena 32-bit aligned:
- if ((long)arena % __alignof__(uint32_t) != 0)
- arena += __alignof__(uint32_t) - ((long)arena % __alignof__(uint32_t));
+ if ((size_t)arena % __alignof__(ucs4_t) != 0)
+ arena += __alignof__(ucs4_t) - ((size_t)arena % __alignof__(ucs4_t));
// If we have filled up this arena, allocate a new one:
- size_t needed_memory = sizeof(uint32_t[1+utf32_len]) + sizeof(uint8_t[u8_len + 1]);
+ size_t needed_memory = sizeof(ucs4_t[1+utf32_len]) + sizeof(uint8_t[u8_len + 1]);
if (arena + needed_memory > arena_end) {
// Do reasonably big chunks at a time, so most synthetic codepoints are
// nearby each other in memory and cache locality is good. This is a
@@ -184,10 +186,10 @@ int32_t get_synthetic_grapheme(const uint32_t *codepoints, int64_t utf32_len)
}
// Copy length-prefixed UTF32 codepoints into the arena and store where they live:
- uint32_t *codepoint_copy = arena;
- mempcpy(codepoint_copy, length_prefixed, sizeof(uint32_t[1+utf32_len]));
+ ucs4_t *codepoint_copy = arena;
+ mempcpy(codepoint_copy, length_prefixed, sizeof(ucs4_t[1+utf32_len]));
synthetic_graphemes[-grapheme_id-1].utf32_cluster = codepoint_copy;
- arena += sizeof(uint32_t[1+utf32_len]);
+ arena += sizeof(ucs4_t[1+utf32_len]);
// Copy UTF8 bytes into the arena and store where they live:
uint8_t *utf8_final = arena;
@@ -199,7 +201,7 @@ int32_t get_synthetic_grapheme(const uint32_t *codepoints, int64_t utf32_len)
// Sickos at the unicode consortium decreed that you can have grapheme clusters
// that begin with *prefix* modifiers, so we gotta check for that case:
synthetic_graphemes[-grapheme_id-1].main_codepoint = length_prefixed[1];
- for (uint32_t i = 0; i < utf32_len; i++) {
+ for (ucs4_t i = 0; i < utf32_len; i++) {
if (!__builtin_expect(uc_is_property_prepended_concatenation_mark(length_prefixed[1+i]), 0)) {
synthetic_graphemes[-grapheme_id-1].main_codepoint = length_prefixed[1+i];
break;
@@ -215,7 +217,7 @@ int32_t get_synthetic_grapheme(const uint32_t *codepoints, int64_t utf32_len)
return grapheme_id;
}
-static inline int64_t num_subtexts(Text_t t)
+PUREFUNC static inline int64_t num_subtexts(Text_t t)
{
if (t.tag != TEXT_SUBTEXT) return 1;
int64_t len = t.length;
@@ -259,8 +261,8 @@ public int Text$print(FILE *stream, Text_t t)
if (t.length == 0) return 0;
switch (t.tag) {
- case TEXT_SHORT_ASCII: return fwrite(t.short_ascii, sizeof(char), t.length, stream);
- case TEXT_ASCII: return fwrite(t.ascii, sizeof(char), t.length, stream);
+ case TEXT_SHORT_ASCII: return fwrite(t.short_ascii, sizeof(char), (size_t)t.length, stream);
+ case TEXT_ASCII: return fwrite(t.ascii, sizeof(char), (size_t)t.length, stream);
case TEXT_GRAPHEMES: case TEXT_SHORT_GRAPHEMES: {
const int32_t *graphemes = t.tag == TEXT_SHORT_GRAPHEMES ? t.short_graphemes : t.graphemes;
int written = 0;
@@ -269,13 +271,13 @@ public int Text$print(FILE *stream, Text_t t)
if (grapheme >= 0) {
uint8_t buf[8];
size_t len = sizeof(buf);
- uint8_t *u8 = u32_to_u8((uint32_t*)&grapheme, 1, buf, &len);
- written += fwrite(u8, sizeof(char), len, stream);
+ uint8_t *u8 = u32_to_u8((ucs4_t*)&grapheme, 1, buf, &len);
+ written += (int)fwrite(u8, sizeof(char), len, stream);
if (u8 != buf) free(u8);
} else {
const uint8_t *u8 = GRAPHEME_UTF8(grapheme);
assert(u8);
- written += fwrite(u8, sizeof(uint8_t), strlen((char*)u8), stream);
+ written += (int)fwrite(u8, sizeof(uint8_t), strlen((char*)u8), stream);
}
}
return written;
@@ -309,10 +311,10 @@ static bool is_concat_stable(Text_t a, Text_t b)
return true;
// Do a normalization run for these two codepoints and see if it looks different:
- uint32_t codepoints[2] = {(uint32_t)last_a, (uint32_t)first_b};
- uint32_t norm_buf[3*2]; // Normalization should not exceed 3x in the input length
+ ucs4_t codepoints[2] = {(ucs4_t)last_a, (ucs4_t)first_b};
+ ucs4_t norm_buf[3*2]; // Normalization should not exceed 3x in the input length
size_t norm_length = sizeof(norm_buf)/sizeof(norm_buf[0]);
- uint32_t *normalized = u32_normalize(UNINORM_NFC, codepoints, 2, norm_buf, &norm_length);
+ ucs4_t *normalized = u32_normalize(UNINORM_NFC, codepoints, 2, norm_buf, &norm_length);
if (norm_length != 2) {
// Looks like these two codepoints merged into one (or maybe had a child, who knows?)
if (normalized != norm_buf) free(normalized);
@@ -387,14 +389,14 @@ static Text_t concat2(Text_t a, Text_t b)
int32_t first_b = get_grapheme(b, 0);
size_t utf32_len = (last_a >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(last_a)) + (first_b >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(first_b));
- uint32_t join_graphemes[utf32_len] = {};
- uint32_t *p = &join_graphemes[0];
+ ucs4_t join_graphemes[utf32_len] = {};
+ ucs4_t *p = &join_graphemes[0];
if (last_a < 0) p = mempcpy(p, GRAPHEME_CODEPOINTS(last_a), NUM_GRAPHEME_CODEPOINTS(last_a));
- else *(p++) = last_a;
+ else *(p++) = (ucs4_t)last_a;
if (first_b < 0) p = mempcpy(p, GRAPHEME_CODEPOINTS(first_b), NUM_GRAPHEME_CODEPOINTS(first_b));
- else *(p++) = first_b;
+ else *(p++) = (ucs4_t)first_b;
- Text_t glue = text_from_u32(join_graphemes, utf32_len, true);
+ Text_t glue = text_from_u32(join_graphemes, (int64_t)utf32_len, true);
if (a.length == 1 && b.length == 1)
return glue;
@@ -510,7 +512,7 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
.tag=TEXT_SHORT_ASCII,
.length=last - first + 1,
};
- memcpy(ret.short_ascii, text.short_ascii + (first-1), ret.length);
+ memcpy(ret.short_ascii, text.short_ascii + (first-1), (size_t)ret.length);
return ret;
}
case TEXT_ASCII: {
@@ -575,15 +577,15 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
}
}
-Text_t text_from_u32(uint32_t *codepoints, int64_t num_codepoints, bool normalize)
+Text_t text_from_u32(ucs4_t *codepoints, int64_t num_codepoints, bool normalize)
{
// Normalization is apparently guaranteed to never exceed 3x in the input length
- uint32_t norm_buf[MIN(256, 3*num_codepoints)];
+ ucs4_t norm_buf[MIN(256, 3*num_codepoints)];
if (normalize) {
size_t norm_length = sizeof(norm_buf)/sizeof(norm_buf[0]);
- uint32_t *normalized = u32_normalize(UNINORM_NFC, codepoints, num_codepoints, norm_buf, &norm_length);
+ ucs4_t *normalized = u32_normalize(UNINORM_NFC, codepoints, (size_t)num_codepoints, norm_buf, &norm_length);
codepoints = normalized;
- num_codepoints = norm_length;
+ num_codepoints = (int64_t)norm_length;
}
// char breaks[num_codepoints];
@@ -593,7 +595,7 @@ Text_t text_from_u32(uint32_t *codepoints, int64_t num_codepoints, bool normaliz
.length=0,
.tag=TEXT_SHORT_GRAPHEMES,
};
- const uint32_t *src = codepoints;
+ const ucs4_t *src = codepoints;
int32_t *graphemes = ret.short_graphemes;
while (src < &codepoints[num_codepoints]) {
if (ret.tag == TEXT_SHORT_GRAPHEMES && ret.length + 1 > 2) {
@@ -605,7 +607,7 @@ Text_t text_from_u32(uint32_t *codepoints, int64_t num_codepoints, bool normaliz
}
// TODO: use grapheme breaks instead of u32_grapheme_next()
- const uint32_t *next = u32_grapheme_next(src, &codepoints[num_codepoints]);
+ const ucs4_t *next = u32_grapheme_next(src, &codepoints[num_codepoints]);
if (next == &src[1]) {
graphemes[ret.length] = (int32_t)*src;
} else {
@@ -640,11 +642,11 @@ public Text_t Text$from_strn(const char *str, size_t len)
if (u8_check((uint8_t*)str, len) != NULL)
return Text("");
- uint32_t buf[128];
+ ucs4_t buf[128];
size_t length = sizeof(buf)/sizeof(buf[0]);
- uint32_t *codepoints = u8_to_u32((uint8_t*)str, ascii_span + strlen(str + ascii_span), buf, &length);
- Text_t ret = text_from_u32(codepoints, length, true);
+ ucs4_t *codepoints = u8_to_u32((uint8_t*)str, (size_t)ascii_span + strlen(str + ascii_span), buf, &length);
+ Text_t ret = text_from_u32(codepoints, (int64_t)length, true);
if (codepoints != buf) free(codepoints);
return ret;
}
@@ -661,11 +663,11 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
case TEXT_ASCII: case TEXT_SHORT_ASCII: {
if (*i + text.length > (int64_t)*capacity) {
*capacity = *i + text.length + 1;
- *buf = GC_REALLOC(*buf, *capacity);
+ *buf = GC_REALLOC(*buf, (size_t)*capacity);
}
const char *bytes = text.tag == TEXT_ASCII ? text.ascii : text.short_ascii;
- memcpy(*buf + *i, bytes, text.length);
+ memcpy(*buf + *i, bytes, (size_t)text.length);
*i += text.length;
break;
}
@@ -675,26 +677,26 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
if (graphemes[g] >= 0) {
uint8_t u8_buf[64];
size_t u8_len = sizeof(u8_buf);
- uint8_t *u8 = u32_to_u8((uint32_t*)&graphemes[g], 1, u8_buf, &u8_len);
+ uint8_t *u8 = u32_to_u8((ucs4_t*)&graphemes[g], 1, u8_buf, &u8_len);
if (*i + (int64_t)u8_len > (int64_t)*capacity) {
- *capacity = *i + u8_len + 1;
- *buf = GC_REALLOC(*buf, *capacity);
+ *capacity = *i + (int64_t)u8_len + 1;
+ *buf = GC_REALLOC(*buf, (size_t)*capacity);
}
memcpy(*buf + *i, u8, u8_len);
- *i += u8_len;
+ *i += (int64_t)u8_len;
if (u8 != u8_buf) free(u8);
} else {
const uint8_t *u8 = GRAPHEME_UTF8(graphemes[g]);
size_t u8_len = u8_strlen(u8);
if (*i + (int64_t)u8_len > (int64_t)*capacity) {
- *capacity = *i + u8_len + 1;
- *buf = GC_REALLOC(*buf, *capacity);
+ *capacity = *i + (int64_t)u8_len + 1;
+ *buf = GC_REALLOC(*buf, (size_t)*capacity);
}
memcpy(*buf + *i, u8, u8_len);
- *i += u8_len;
+ *i += (int64_t)u8_len;
}
}
break;
@@ -713,19 +715,19 @@ static void u8_buf_append(Text_t text, char **buf, int64_t *capacity, int64_t *i
public char *Text$as_c_string(Text_t text)
{
int64_t capacity = text.length + 1;
- char *buf = GC_MALLOC_ATOMIC(capacity);
+ char *buf = GC_MALLOC_ATOMIC((size_t)capacity);
int64_t i = 0;
u8_buf_append(text, &buf, &capacity, &i);
if (i + 1 > (int64_t)capacity) {
capacity = i + 1;
- buf = GC_REALLOC(buf, capacity);
+ buf = GC_REALLOC(buf, (size_t)capacity);
}
buf[i] = '\0';
return buf;
}
-public uint64_t Text$hash(Text_t *text)
+PUREFUNC public uint64_t Text$hash(Text_t *text)
{
if (text->hash != 0) return text->hash;
siphash sh;
@@ -819,7 +821,7 @@ public uint64_t Text$hash(Text_t *text)
++sub_i;
}
- text->hash = siphashfinish_last_part(&sh, leftover);
+ text->hash = siphashfinish_last_part(&sh, (uint64_t)leftover);
break;
}
default: errx(1, "Invalid text");
@@ -831,7 +833,7 @@ public uint64_t Text$hash(Text_t *text)
return text->hash;
}
-int32_t _next_grapheme(Text_t text, text_iter_t *state, int64_t index)
+int32_t _get_grapheme(Text_t text, text_iter_t *state, int64_t index)
{
switch (text.tag) {
case TEXT_ASCII: return index < text.length ? (int32_t)text.ascii[index] : 0;
@@ -851,7 +853,7 @@ int32_t _next_grapheme(Text_t text, text_iter_t *state, int64_t index)
}
for (;;) {
if (index < state->sum_of_previous_subtexts + text.subtexts[state->subtext].length)
- return _next_grapheme(text.subtexts[state->subtext], NULL, index - state->sum_of_previous_subtexts);
+ return _get_grapheme(text.subtexts[state->subtext], NULL, index - state->sum_of_previous_subtexts);
state->sum_of_previous_subtexts += text.subtexts[state->subtext].length;
state->subtext += 1;
}
@@ -865,32 +867,32 @@ int32_t _next_grapheme(Text_t text, text_iter_t *state, int64_t index)
int32_t get_grapheme(Text_t text, int64_t index)
{
text_iter_t state = {0, 0};
- return _next_grapheme(text, &state, index);
+ return _get_grapheme(text, &state, index);
}
-public int32_t Text$compare(const Text_t *a, const Text_t *b)
+PUREFUNC public int32_t Text$compare(const Text_t *a, const Text_t *b)
{
if (a == b) return 0;
int64_t len = MAX(a->length, b->length);
text_iter_t a_state = {0, 0}, b_state = {0, 0};
for (int64_t i = 0; i < len; i++) {
- int32_t ai = _next_grapheme(*a, &a_state, i);
- int32_t bi = _next_grapheme(*b, &b_state, i);
+ int32_t ai = _get_grapheme(*a, &a_state, i);
+ int32_t bi = _get_grapheme(*b, &b_state, i);
if (ai == bi) continue;
int32_t cmp;
if (ai > 0 && bi > 0) {
- cmp = u32_cmp((uint32_t*)&ai, (uint32_t*)&bi, 1);
+ cmp = u32_cmp((ucs4_t*)&ai, (ucs4_t*)&bi, 1);
} else if (ai > 0) {
cmp = u32_cmp2(
- (uint32_t*)&ai, 1,
+ (ucs4_t*)&ai, 1,
GRAPHEME_CODEPOINTS(bi),
NUM_GRAPHEME_CODEPOINTS(bi));
} else if (bi > 0) {
cmp = u32_cmp2(
GRAPHEME_CODEPOINTS(ai),
NUM_GRAPHEME_CODEPOINTS(ai),
- (uint32_t*)&bi, 1);
+ (ucs4_t*)&bi, 1);
} else {
cmp = u32_cmp2(
GRAPHEME_CODEPOINTS(ai),
@@ -903,7 +905,7 @@ public int32_t Text$compare(const Text_t *a, const Text_t *b)
return 0;
}
-public bool Text$equal(const Text_t *a, const Text_t *b)
+PUREFUNC public bool Text$equal(const Text_t *a, const Text_t *b)
{
if (a == b) return true;
@@ -912,14 +914,14 @@ public bool Text$equal(const Text_t *a, const Text_t *b)
int64_t len = a->length;
text_iter_t a_state = {0, 0}, b_state = {0, 0};
for (int64_t i = 0; i < len; i++) {
- int32_t ai = _next_grapheme(*a, &a_state, i);
- int32_t bi = _next_grapheme(*b, &b_state, i);
+ int32_t ai = _get_grapheme(*a, &a_state, i);
+ int32_t bi = _get_grapheme(*b, &b_state, i);
if (ai != bi) return false;
}
return true;
}
-public bool Text$equal_ignoring_case(Text_t a, Text_t b)
+PUREFUNC public bool Text$equal_ignoring_case(Text_t a, Text_t b)
{
if (a.length != b.length)
return false;
@@ -927,17 +929,17 @@ public bool Text$equal_ignoring_case(Text_t a, Text_t b)
text_iter_t a_state = {0, 0}, b_state = {0, 0};
const char *language = uc_locale_language();
for (int64_t i = 0; i < len; i++) {
- int32_t ai = _next_grapheme(a, &a_state, i);
- int32_t bi = _next_grapheme(b, &b_state, i);
+ int32_t ai = _get_grapheme(a, &a_state, i);
+ int32_t bi = _get_grapheme(b, &b_state, i);
if (ai != bi) {
- const uint32_t *a_codepoints = ai >= 0 ? (uint32_t*)&ai : GRAPHEME_CODEPOINTS(ai);
+ const ucs4_t *a_codepoints = ai >= 0 ? (ucs4_t*)&ai : GRAPHEME_CODEPOINTS(ai);
int64_t a_len = ai >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(ai);
- const uint32_t *b_codepoints = bi >= 0 ? (uint32_t*)&bi : GRAPHEME_CODEPOINTS(bi);
+ const ucs4_t *b_codepoints = bi >= 0 ? (ucs4_t*)&bi : GRAPHEME_CODEPOINTS(bi);
int64_t b_len = bi >= 0 ? 1 : NUM_GRAPHEME_CODEPOINTS(bi);
int cmp = 0;
- (void)u32_casecmp(a_codepoints, a_len, b_codepoints, b_len, language, UNINORM_NFC, &cmp);
+ (void)u32_casecmp(a_codepoints, (size_t)a_len, b_codepoints, (size_t)b_len, language, UNINORM_NFC, &cmp);
if (cmp != 0)
return false;
}
@@ -950,10 +952,10 @@ public Text_t Text$upper(Text_t text)
if (text.length == 0) return text;
Array_t codepoints = Text$utf32_codepoints(text);
const char *language = uc_locale_language();
- uint32_t buf[128];
+ ucs4_t buf[128];
size_t out_len = sizeof(buf)/sizeof(buf[0]);
- uint32_t *upper = u32_toupper(codepoints.data, codepoints.length, language, UNINORM_NFC, buf, &out_len);
- Text_t ret = text_from_u32(upper, out_len, false);
+ ucs4_t *upper = u32_toupper(codepoints.data, (size_t)codepoints.length, language, UNINORM_NFC, buf, &out_len);
+ Text_t ret = text_from_u32(upper, (int64_t)out_len, false);
if (upper != buf) free(upper);
return ret;
}
@@ -963,10 +965,10 @@ public Text_t Text$lower(Text_t text)
if (text.length == 0) return text;
Array_t codepoints = Text$utf32_codepoints(text);
const char *language = uc_locale_language();
- uint32_t buf[128];
+ ucs4_t buf[128];
size_t out_len = sizeof(buf)/sizeof(buf[0]);
- uint32_t *lower = u32_tolower(codepoints.data, codepoints.length, language, UNINORM_NFC, buf, &out_len);
- Text_t ret = text_from_u32(lower, out_len, false);
+ ucs4_t *lower = u32_tolower(codepoints.data, (size_t)codepoints.length, language, UNINORM_NFC, buf, &out_len);
+ Text_t ret = text_from_u32(lower, (int64_t)out_len, false);
if (lower != buf) free(lower);
return ret;
}
@@ -976,10 +978,10 @@ public Text_t Text$title(Text_t text)
if (text.length == 0) return text;
Array_t codepoints = Text$utf32_codepoints(text);
const char *language = uc_locale_language();
- uint32_t buf[128];
+ ucs4_t buf[128];
size_t out_len = sizeof(buf)/sizeof(buf[0]);
- uint32_t *title = u32_totitle(codepoints.data, codepoints.length, language, UNINORM_NFC, buf, &out_len);
- Text_t ret = text_from_u32(title, out_len, false);
+ ucs4_t *title = u32_totitle(codepoints.data, (size_t)codepoints.length, language, UNINORM_NFC, buf, &out_len);
+ Text_t ret = text_from_u32(title, (int64_t)out_len, false);
if (title != buf) free(title);
return ret;
}
@@ -988,8 +990,8 @@ static inline void skip_whitespace(Text_t text, int64_t *i)
{
text_iter_t state = {0, 0};
while (*i < text.length) {
- int32_t grapheme = _next_grapheme(text, &state, *i);
- if (grapheme > 0 && !uc_is_property_white_space(grapheme))
+ int32_t grapheme = _get_grapheme(text, &state, *i);
+ if (grapheme > 0 && !uc_is_property_white_space((ucs4_t)grapheme))
return;
*i += 1;
}
@@ -1009,7 +1011,7 @@ static inline bool match_str(Text_t text, int64_t *i, const char *str)
text_iter_t state = {0, 0};
int64_t matched = 0;
while (matched[str]) {
- if (*i + matched >= text.length || _next_grapheme(text, &state, *i + matched) != str[matched])
+ if (*i + matched >= text.length || _get_grapheme(text, &state, *i + matched) != str[matched])
return false;
matched += 1;
}
@@ -1022,9 +1024,7 @@ static inline bool match_property(Text_t text, int64_t *i, uc_property_t prop)
if (*i >= text.length) return false;
int32_t grapheme = get_grapheme(text, *i);
// TODO: check every codepoint in the cluster?
- grapheme = MAIN_GRAPHEME_CODEPOINT(grapheme);
-
- if (uc_is_property(grapheme, prop)) {
+ if (uc_is_property(MAIN_GRAPHEME_CODEPOINT(grapheme), prop)) {
*i += 1;
return true;
}
@@ -1036,9 +1036,8 @@ static int64_t parse_int(Text_t text, int64_t *i)
text_iter_t state = {0, 0};
int64_t value = 0;
for (;; *i += 1) {
- int32_t grapheme = _next_grapheme(text, &state, *i);
- grapheme = MAIN_GRAPHEME_CODEPOINT(grapheme);
- int digit = uc_digit_value(grapheme);
+ ucs4_t grapheme = _get_main_grapheme(text, &state, *i);
+ int digit = uc_digit_value((ucs4_t)grapheme);
if (digit < 0) break;
if (value >= INT64_MAX/10) break;
value = 10*value + digit;
@@ -1053,7 +1052,7 @@ const char *get_property_name(Text_t text, int64_t *i)
char *dest = name;
text_iter_t state = {0, 0};
while (*i < text.length) {
- int32_t grapheme = _next_grapheme(text, &state, *i);
+ int32_t grapheme = _get_grapheme(text, &state, *i);
if (!(grapheme & ~0xFF) && (isalnum(grapheme) || grapheme == ' ' || grapheme == '_' || grapheme == '-')) {
*dest = (char)grapheme;
++dest;
@@ -1074,16 +1073,16 @@ const char *get_property_name(Text_t text, int64_t *i)
}
#define EAT1(text, state, index, cond) ({\
- int32_t grapheme = _next_grapheme(text, state, index); \
+ int32_t grapheme = _get_grapheme(text, state, index); \
bool success = (cond); \
if (success) index += 1; \
success; })
#define EAT2(text, state, index, cond1, cond2) ({\
- int32_t grapheme = _next_grapheme(text, state, index); \
+ int32_t grapheme = _get_grapheme(text, state, index); \
bool success = (cond1); \
if (success) { \
- grapheme = _next_grapheme(text, state, index + 1); \
+ grapheme = _get_grapheme(text, state, index + 1); \
success = (cond2); \
if (success) \
index += 2; \
@@ -1102,9 +1101,8 @@ int64_t match_email(Text_t text, int64_t index)
text_iter_t state = {0, 0};
if (index > 0) {
- int32_t prev_codepoint = _next_grapheme(text, &state, index - 1);
- prev_codepoint = MAIN_GRAPHEME_CODEPOINT(prev_codepoint);
- if (uc_is_property_alphabetic(prev_codepoint))
+ ucs4_t prev_codepoint = _get_main_grapheme(text, &state, index - 1);
+ if (uc_is_property_alphabetic((ucs4_t)prev_codepoint))
return -1;
}
@@ -1148,7 +1146,7 @@ int64_t match_ipv6(Text_t text, int64_t index)
{
text_iter_t state = {0, 0};
if (index > 0) {
- int32_t prev_codepoint = _next_grapheme(text, &state, index - 1);
+ int32_t prev_codepoint = _get_grapheme(text, &state, index - 1);
if ((prev_codepoint & ~0x7F) && (isxdigit(prev_codepoint) || prev_codepoint == ':'))
return -1;
}
@@ -1184,7 +1182,7 @@ static int64_t match_ipv4(Text_t text, int64_t index)
{
text_iter_t state = {0, 0};
if (index > 0) {
- int32_t prev_codepoint = _next_grapheme(text, &state, index - 1);
+ int32_t prev_codepoint = _get_grapheme(text, &state, index - 1);
if ((prev_codepoint & ~0x7F) && (isdigit(prev_codepoint) || prev_codepoint == '.'))
return -1;
}
@@ -1226,9 +1224,8 @@ int64_t match_uri(Text_t text, int64_t index)
text_iter_t state = {0, 0};
if (index > 0) {
- int32_t prev_codepoint = _next_grapheme(text, &state, index - 1);
- prev_codepoint = MAIN_GRAPHEME_CODEPOINT(prev_codepoint);
- if (uc_is_property_alphabetic(prev_codepoint))
+ int32_t prev_codepoint = _get_grapheme(text, &state, index - 1);
+ if (uc_is_property_alphabetic(MAIN_GRAPHEME_CODEPOINT(prev_codepoint)))
return -1;
}
@@ -1315,15 +1312,15 @@ int64_t match_url(Text_t text, int64_t index)
int64_t match_id(Text_t text, int64_t index)
{
text_iter_t state = {0, 0};
- if (!EAT1(text, &state, index, uc_is_property(grapheme, UC_PROPERTY_XID_START)))
+ if (!EAT1(text, &state, index, uc_is_property((ucs4_t)grapheme, UC_PROPERTY_XID_START)))
return -1;
- return 1 + EAT_MANY(text, &state, index, uc_is_property(grapheme, UC_PROPERTY_XID_CONTINUE));
+ return 1 + EAT_MANY(text, &state, index, uc_is_property((ucs4_t)grapheme, UC_PROPERTY_XID_CONTINUE));
}
int64_t match_int(Text_t text, int64_t index)
{
text_iter_t state = {0, 0};
- int64_t len = EAT_MANY(text, &state, index, uc_is_property(grapheme, UC_PROPERTY_DECIMAL_DIGIT));
+ int64_t len = EAT_MANY(text, &state, index, uc_is_property((ucs4_t)grapheme, UC_PROPERTY_DECIMAL_DIGIT));
return len >= 0 ? len : -1;
}
@@ -1332,10 +1329,10 @@ int64_t match_num(Text_t text, int64_t index)
text_iter_t state = {0, 0};
bool negative = EAT1(text, &state, index, grapheme == '-') ? 1 : 0;
int64_t pre_decimal = EAT_MANY(text, &state, index,
- uc_is_property(grapheme, UC_PROPERTY_DECIMAL_DIGIT));
+ uc_is_property((ucs4_t)grapheme, UC_PROPERTY_DECIMAL_DIGIT));
bool decimal = (EAT1(text, &state, index, grapheme == '.') == 1);
int64_t post_decimal = decimal ? EAT_MANY(text, &state, index,
- uc_is_property(grapheme, UC_PROPERTY_DECIMAL_DIGIT)) : 0;
+ uc_is_property((ucs4_t)grapheme, UC_PROPERTY_DECIMAL_DIGIT)) : 0;
if (pre_decimal == 0 && post_decimal == 0)
return -1;
return negative + pre_decimal + decimal + post_decimal;
@@ -1347,11 +1344,10 @@ int64_t match_newline(Text_t text, int64_t index)
return -1;
text_iter_t state = {0, 0};
- int32_t grapheme = index >= text.length ? 0 : _next_grapheme(text, &state, index);
- grapheme = MAIN_GRAPHEME_CODEPOINT(grapheme);
+ ucs4_t grapheme = index >= text.length ? 0 : _get_main_grapheme(text, &state, index);
if (grapheme == '\n')
return 1;
- if (grapheme == '\r' && _next_grapheme(text, &state, index + 1) == '\n')
+ if (grapheme == '\r' && _get_grapheme(text, &state, index + 1) == '\n')
return 2;
return -1;
}
@@ -1376,8 +1372,7 @@ typedef struct {
int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
{
- int32_t grapheme = index >= text.length ? 0 : _next_grapheme(text, state, index);
- grapheme = MAIN_GRAPHEME_CODEPOINT(grapheme);
+ int32_t grapheme = index >= text.length ? 0 : _get_grapheme(text, state, index);
switch (pat.tag) {
case PAT_START: {
@@ -1404,7 +1399,7 @@ int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
case PAT_PROPERTY: {
if (index >= text.length)
return -1;
- else if (uc_is_property(grapheme, pat.property))
+ else if (uc_is_property((ucs4_t)grapheme, pat.property))
return pat.negated ? -1 : 1;
return pat.negated ? 1 : -1;
}
@@ -1424,7 +1419,7 @@ int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
if (index + match_len >= text.length)
return pat.negated ? 1 : -1;
- int32_t c = _next_grapheme(text, state, index + match_len);
+ int32_t c = _get_grapheme(text, state, index + match_len);
if (c == open)
depth += 1;
else if (c == close)
@@ -1443,7 +1438,7 @@ int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
int32_t close = pat.quote_graphemes[1];
for (int64_t i = index + 1; i < text.length; i++) {
- int32_t c = _next_grapheme(text, state, i);
+ int32_t c = _get_grapheme(text, state, i);
if (c == close) {
return pat.negated ? -1 : (i - index) + 1;
} else if (c == '\\' && index + 1 < text.length) {
@@ -1458,6 +1453,7 @@ int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
return pat.negated ? -1 : match_len;
return pat.negated ? 1 : -1;
}
+ default: errx(1, "Invalid pattern");
}
errx(1, "Unreachable");
}
@@ -1465,12 +1461,12 @@ int64_t match_pat(Text_t text, text_iter_t *state, int64_t index, pat_t pat)
pat_t parse_next_pat(Text_t pattern, text_iter_t *state, int64_t *index)
{
if (EAT2(pattern, state, *index,
- uc_is_property(grapheme, UC_PROPERTY_QUOTATION_MARK),
+ uc_is_property((ucs4_t)grapheme, UC_PROPERTY_QUOTATION_MARK),
grapheme == '?')) {
// Quotations: "?", '?', etc
- int32_t open = _next_grapheme(pattern, state, *index-2);
+ int32_t open = _get_grapheme(pattern, state, *index-2);
int32_t close = open;
- uc_mirror_char(open, (uint32_t*)&close);
+ uc_mirror_char((ucs4_t)open, (ucs4_t*)&close);
if (!match_grapheme(pattern, index, close))
fail("Pattern's closing quote is missing: %k", &pattern);
@@ -1480,12 +1476,12 @@ pat_t parse_next_pat(Text_t pattern, text_iter_t *state, int64_t *index)
.quote_graphemes={open, close},
};
} else if (EAT2(pattern, state, *index,
- uc_is_property(grapheme, UC_PROPERTY_PAIRED_PUNCTUATION),
+ uc_is_property((ucs4_t)grapheme, UC_PROPERTY_PAIRED_PUNCTUATION),
grapheme == '?')) {
// Nested punctuation: (?), [?], etc
- int32_t open = _next_grapheme(pattern, state, *index-2);
+ int32_t open = _get_grapheme(pattern, state, *index-2);
int32_t close = open;
- uc_mirror_char(open, (uint32_t*)&close);
+ uc_mirror_char((ucs4_t)open, (ucs4_t*)&close);
if (!match_grapheme(pattern, index, close))
fail("Pattern's closing brace is missing: %k", &pattern);
@@ -1498,7 +1494,7 @@ pat_t parse_next_pat(Text_t pattern, text_iter_t *state, int64_t *index)
grapheme == '{')) { // named patterns {id}, {2-3 hex}, etc.
skip_whitespace(pattern, index);
int64_t min, max;
- if (uc_is_digit(_next_grapheme(pattern, state, *index))) {
+ if (uc_is_digit((ucs4_t)_get_grapheme(pattern, state, *index))) {
min = parse_int(pattern, index);
skip_whitespace(pattern, index);
if (match_grapheme(pattern, index, '+')) {
@@ -1526,7 +1522,7 @@ pat_t parse_next_pat(Text_t pattern, text_iter_t *state, int64_t *index)
if (!prop_name) {
// Literal character, e.g. {1?}
skip_whitespace(pattern, index);
- int32_t grapheme = _next_grapheme(pattern, state, (*index)++);
+ int32_t grapheme = _get_grapheme(pattern, state, (*index)++);
if (!match_grapheme(pattern, index, '}'))
fail("Missing closing '}' in pattern: %k", &pattern);
return PAT(PAT_GRAPHEME, .grapheme=grapheme);
@@ -1598,19 +1594,20 @@ pat_t parse_next_pat(Text_t pattern, text_iter_t *state, int64_t *index)
return PAT(PAT_FUNCTION, .fn=match_url);
}
break;
+ default: break;
}
uc_property_t prop = uc_property_byname(prop_name);
if (uc_property_is_valid(prop))
return PAT(PAT_PROPERTY, .property=prop);
- uint32_t grapheme = unicode_name_character(prop_name);
+ ucs4_t grapheme = unicode_name_character(prop_name);
if (grapheme == UNINAME_INVALID)
fail("Not a valid property or character name: %s", prop_name);
- return PAT(PAT_GRAPHEME, .grapheme=grapheme);
+ return PAT(PAT_GRAPHEME, .grapheme=(int32_t)grapheme);
#undef PAT
} else {
- return (pat_t){.tag=PAT_GRAPHEME, .non_capturing=true, .min=1, .max=1, .grapheme=_next_grapheme(pattern, state, (*index)++)};
+ return (pat_t){.tag=PAT_GRAPHEME, .non_capturing=true, .min=1, .max=1, .grapheme=_get_grapheme(pattern, state, (*index)++)};
}
}
@@ -1718,15 +1715,15 @@ static int64_t _find(Text_t text, Pattern_t pattern, int64_t first, int64_t last
{
int32_t first_grapheme = get_grapheme(pattern, 0);
bool find_first = (first_grapheme != '{'
- && !uc_is_property(first_grapheme, UC_PROPERTY_QUOTATION_MARK)
- && !uc_is_property(first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
text_iter_t text_state = {0, 0};
for (int64_t i = first; i <= last; i++) {
// Optimization: quickly skip ahead to first char in pattern:
if (find_first) {
- while (i < text.length && _next_grapheme(text, &text_state, i) != first_grapheme)
+ while (i < text.length && _get_grapheme(text, &text_state, i) != first_grapheme)
++i;
}
@@ -1753,13 +1750,13 @@ public Int_t Text$find(Text_t text, Pattern_t pattern, Int_t from_index, int64_t
return I(found+1);
}
-public bool Text$has(Text_t text, Pattern_t pattern)
+PUREFUNC public bool Text$has(Text_t text, Pattern_t pattern)
{
int64_t found = _find(text, pattern, 0, text.length-1, NULL);
return (found >= 0);
}
-public bool Text$matches(Text_t text, Pattern_t pattern)
+PUREFUNC public bool Text$matches(Text_t text, Pattern_t pattern)
{
int64_t m = match(text, 0, pattern, 0, NULL, 0);
return m == text.length;
@@ -1787,18 +1784,18 @@ static inline Text_t _quoted(Text_t text, bool colorize, char quote_char)
{
// TODO: optimize for ASCII and short strings
Array_t graphemes = {.atomic=1};
-#define add_char(c) Array$insert_value(&graphemes, (uint32_t)c, I_small(0), sizeof(uint32_t))
-#define add_str(s) ({ for (char *_c = s; *_c; ++_c) Array$insert_value(&graphemes, (uint32_t)*_c, I_small(0), sizeof(uint32_t)); })
+#define add_char(c) Array$insert_value(&graphemes, (ucs4_t)c, I_small(0), sizeof(ucs4_t))
+#define add_str(s) ({ for (const char *_c = s; *_c; ++_c) Array$insert_value(&graphemes, (ucs4_t)*_c, I_small(0), sizeof(ucs4_t)); })
if (colorize)
add_str("\x1b[35m");
- if (quote_char != '"' && quote_char != '\"' && quote_char != '`')
+ if (quote_char != '"' && quote_char != '\'' && quote_char != '`')
add_char('$');
add_char(quote_char);
#define add_escaped(str) ({ if (colorize) add_str("\x1b[34;1m"); add_char('\\'); add_str(str); if (colorize) add_str("\x1b[0;35m"); })
text_iter_t state = {0, 0};
for (int64_t i = 0; i < text.length; i++) {
- int32_t g = _next_grapheme(text, &state, i);
+ int32_t g = _get_grapheme(text, &state, i);
switch (g) {
case '\a': add_escaped("a"); break;
case '\b': add_escaped("b"); break;
@@ -1886,8 +1883,8 @@ static Text_t apply_backrefs(Text_t text, Pattern_t original_pattern, Text_t rep
int32_t first_grapheme = get_grapheme(backref_pat, 0);
bool find_first = (first_grapheme != '{'
- && !uc_is_property(first_grapheme, UC_PROPERTY_QUOTATION_MARK)
- && !uc_is_property(first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
Text_t ret = Text("");
text_iter_t state = {0, 0};
@@ -1895,7 +1892,7 @@ static Text_t apply_backrefs(Text_t text, Pattern_t original_pattern, Text_t rep
for (int64_t pos = 0; pos < replacement.length; ) {
// Optimization: quickly skip ahead to first char in the backref pattern:
if (find_first) {
- while (pos < replacement.length && _next_grapheme(replacement, &state, pos) != first_grapheme)
+ while (pos < replacement.length && _get_grapheme(replacement, &state, pos) != first_grapheme)
++pos;
}
@@ -1914,7 +1911,7 @@ static Text_t apply_backrefs(Text_t text, Pattern_t original_pattern, Text_t rep
if (backref < 0 || backref > 9) fail("Invalid backref index: %ld (only 0-%d are allowed)", backref, MAX_BACKREFS-1);
backref_len = (after_backref - pos);
- if (_next_grapheme(replacement, &state, pos + backref_len) == ';')
+ if (_get_grapheme(replacement, &state, pos + backref_len) == ';')
backref_len += 1; // skip optional semicolon
if (!captures[backref].occupied)
@@ -1948,15 +1945,15 @@ public Text_t Text$replace(Text_t text, Pattern_t pattern, Text_t replacement, P
int32_t first_grapheme = get_grapheme(pattern, 0);
bool find_first = (first_grapheme != '{'
- && !uc_is_property(first_grapheme, UC_PROPERTY_QUOTATION_MARK)
- && !uc_is_property(first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
text_iter_t text_state = {0, 0};
int64_t nonmatching_pos = 0;
for (int64_t pos = 0; pos < text.length; ) {
// Optimization: quickly skip ahead to first char in pattern:
if (find_first) {
- while (pos < text.length && _next_grapheme(text, &text_state, pos) != first_grapheme)
+ while (pos < text.length && _get_grapheme(text, &text_state, pos) != first_grapheme)
++pos;
}
@@ -2015,8 +2012,8 @@ public Text_t Text$map(Text_t text, Pattern_t pattern, closure_t fn)
int32_t first_grapheme = get_grapheme(pattern, 0);
bool find_first = (first_grapheme != '{'
- && !uc_is_property(first_grapheme, UC_PROPERTY_QUOTATION_MARK)
- && !uc_is_property(first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
text_iter_t text_state = {0, 0};
int64_t nonmatching_pos = 0;
@@ -2025,7 +2022,7 @@ public Text_t Text$map(Text_t text, Pattern_t pattern, closure_t fn)
for (int64_t pos = 0; pos < text.length; pos++) {
// Optimization: quickly skip ahead to first char in pattern:
if (find_first) {
- while (pos < text.length && _next_grapheme(text, &text_state, pos) != first_grapheme)
+ while (pos < text.length && _get_grapheme(text, &text_state, pos) != first_grapheme)
++pos;
}
@@ -2130,6 +2127,7 @@ public Text_t Text$join(Text_t glue, Array_t pieces)
return result;
}
+__attribute__((format(printf, 1, 2)))
public Text_t Text$format(const char *fmt, ...)
{
va_list args;
@@ -2146,8 +2144,8 @@ public Text_t Text$format(const char *fmt, ...)
for (int i = 0; i < len; i++)
ret.short_ascii[i] = buf[i];
} else {
- char *str = GC_MALLOC_ATOMIC(len+1);
- vsnprintf(str, len+1, fmt, args);
+ char *str = GC_MALLOC_ATOMIC((size_t)(len+1));
+ vsnprintf(str, (size_t)(len+1), fmt, args);
ret = Text$from_str(str);
}
va_end(args);
@@ -2169,14 +2167,14 @@ public Array_t Text$utf32_codepoints(Text_t text)
Array_t codepoints = {.atomic=1};
text_iter_t state = {0, 0};
for (int64_t i = 0; i < text.length; i++) {
- int32_t grapheme = _next_grapheme(text, &state, i);
+ int32_t grapheme = _get_grapheme(text, &state, i);
if (grapheme < 0) {
for (int64_t c = 0; c < NUM_GRAPHEME_CODEPOINTS(grapheme); c++) {
- int32_t subg = GRAPHEME_CODEPOINTS(grapheme)[c];
- Array$insert(&codepoints, &subg, I_small(0), sizeof(uint32_t));
+ ucs4_t subg = GRAPHEME_CODEPOINTS(grapheme)[c];
+ Array$insert(&codepoints, &subg, I_small(0), sizeof(ucs4_t));
}
} else {
- Array$insert(&codepoints, &grapheme, I_small(0), sizeof(uint32_t));
+ Array$insert(&codepoints, &grapheme, I_small(0), sizeof(ucs4_t));
}
}
return codepoints;
@@ -2188,7 +2186,7 @@ public Array_t Text$utf8_bytes(Text_t text)
return (Array_t){.length=strlen(str), .stride=1, .atomic=1, .data=(void*)str};
}
-static inline const char *codepoint_name(uint32_t c)
+static inline const char *codepoint_name(ucs4_t c)
{
char *name = GC_MALLOC_ATOMIC(UNINAME_MAX);
char *found_name = unicode_character_name(c, name);
@@ -2204,16 +2202,16 @@ public Array_t Text$codepoint_names(Text_t text)
Array_t names = {};
text_iter_t state = {0, 0};
for (int64_t i = 0; i < text.length; i++) {
- int32_t grapheme = _next_grapheme(text, &state, i);
+ int32_t grapheme = _get_grapheme(text, &state, i);
if (grapheme < 0) {
for (int64_t c = 0; c < NUM_GRAPHEME_CODEPOINTS(grapheme); c++) {
const char *name = codepoint_name(GRAPHEME_CODEPOINTS(grapheme)[c]);
- Text_t name_text = (Text_t){.tag=TEXT_ASCII, .length=strlen(name), .ascii=name};
+ Text_t name_text = (Text_t){.tag=TEXT_ASCII, .length=(int64_t)strlen(name), .ascii=name};
Array$insert(&names, &name_text, I_small(0), sizeof(Text_t));
}
} else {
- const char *name = codepoint_name(grapheme);
- Text_t name_text = (Text_t){.tag=TEXT_ASCII, .length=strlen(name), .ascii=name};
+ const char *name = codepoint_name((ucs4_t)grapheme);
+ Text_t name_text = (Text_t){.tag=TEXT_ASCII, .length=(int64_t)strlen(name), .ascii=name};
Array$insert(&names, &name_text, I_small(0), sizeof(Text_t));
}
}
@@ -2234,9 +2232,9 @@ public Text_t Text$from_codepoint_names(Array_t codepoint_names)
for (int64_t i = 0; i < codepoint_names.length; i++) {
Text_t *name = ((Text_t*)(codepoint_names.data + i*codepoint_names.stride));
const char *name_str = Text$as_c_string(*name);
- uint32_t codepoint = unicode_name_character(name_str);
+ ucs4_t codepoint = unicode_name_character(name_str);
if (codepoint != UNINAME_INVALID)
- Array$insert(&codepoints, &codepoint, I_small(0), sizeof(uint32_t));
+ Array$insert(&codepoints, &codepoint, I_small(0), sizeof(ucs4_t));
}
return Text$from_codepoints(codepoints);
}
@@ -2256,8 +2254,8 @@ public Array_t Text$lines(Text_t text)
Array_t lines = {};
text_iter_t state = {0, 0};
for (int64_t i = 0, line_start = 0; i < text.length; i++) {
- int32_t grapheme = _next_grapheme(text, &state, i);
- if (grapheme == '\r' && _next_grapheme(text, &state, i + 1) == '\n') { // CRLF
+ int32_t grapheme = _get_grapheme(text, &state, i);
+ if (grapheme == '\r' && _get_grapheme(text, &state, i + 1) == '\n') { // CRLF
Text_t line = Text$slice(text, I(line_start+1), I(i));
Array$insert(&lines, &line, I_small(0), sizeof(Text_t));
i += 1; // skip one extra for CR
@@ -2285,12 +2283,12 @@ public Pattern_t Pattern$escape_text(Text_t text)
{
// TODO: optimize for ASCII and short strings
Array_t graphemes = {.atomic=1};
-#define add_char(c) Array$insert_value(&graphemes, (uint32_t)c, I_small(0), sizeof(uint32_t))
-#define add_str(s) ({ for (char *_c = s; *_c; ++_c) Array$insert_value(&graphemes, (uint32_t)*_c, I_small(0), sizeof(uint32_t)); })
+#define add_char(c) Array$insert_value(&graphemes, (ucs4_t)c, I_small(0), sizeof(ucs4_t))
+#define add_str(s) ({ for (const char *_c = s; *_c; ++_c) Array$insert_value(&graphemes, (ucs4_t)*_c, I_small(0), sizeof(ucs4_t)); })
text_iter_t state = {0, 0};
for (int64_t i = 0; i < text.length; i++) {
- int32_t g = _next_grapheme(text, &state, i);
- uint32_t g0 = g < 0 ? GRAPHEME_CODEPOINTS(g)[0] : (uint32_t)g;
+ int32_t g = _get_grapheme(text, &state, i);
+ ucs4_t g0 = g < 0 ? GRAPHEME_CODEPOINTS(g)[0] : (ucs4_t)g;
if (g == '{') {
add_str("{1{}");
diff --git a/builtins/text.h b/builtins/text.h
index 56473e3a..a9fbf1a1 100644
--- a/builtins/text.h
+++ b/builtins/text.h
@@ -24,10 +24,10 @@ Text_t Text$_concat(int n, Text_t items[n]);
Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int);
Text_t Text$from_str(const char *str);
Text_t Text$from_strn(const char *str, size_t len);
-uint64_t Text$hash(Text_t *text);
-int32_t Text$compare(const Text_t *a, const Text_t *b);
-bool Text$equal(const Text_t *a, const Text_t *b);
-bool Text$equal_ignoring_case(Text_t a, Text_t b);
+PUREFUNC uint64_t Text$hash(Text_t *text);
+PUREFUNC int32_t Text$compare(const Text_t *a, const Text_t *b);
+PUREFUNC bool Text$equal(const Text_t *a, const Text_t *b);
+PUREFUNC bool Text$equal_ignoring_case(Text_t a, Text_t b);
Text_t Text$upper(Text_t text);
Text_t Text$lower(Text_t text);
Text_t Text$title(Text_t text);
@@ -39,9 +39,10 @@ Array_t Text$split(Text_t text, Pattern_t pattern);
Text_t Text$trim(Text_t text, Pattern_t pattern, bool trim_left, bool trim_right);
Int_t Text$find(Text_t text, Pattern_t pattern, Int_t i, int64_t *match_length);
Array_t Text$find_all(Text_t text, Pattern_t pattern);
-bool Text$has(Text_t text, Pattern_t pattern);
-bool Text$matches(Text_t text, Pattern_t pattern);
+PUREFUNC bool Text$has(Text_t text, Pattern_t pattern);
+PUREFUNC bool Text$matches(Text_t text, Pattern_t pattern);
char *Text$as_c_string(Text_t text);
+__attribute__((format(printf, 1, 2)))
public Text_t Text$format(const char *fmt, ...);
Array_t Text$clusters(Text_t text);
Array_t Text$utf32_codepoints(Text_t text);
diff --git a/builtins/types.h b/builtins/types.h
index 0b48ab36..f06730a7 100644
--- a/builtins/types.h
+++ b/builtins/types.h
@@ -45,6 +45,7 @@ typedef struct TypeInfo {
struct {
const char *type_str;
} TypeInfoInfo;
+#pragma GCC diagnostic ignored "-Wpedantic"
struct {} OpaqueInfo;
struct {
const char *name;
diff --git a/builtins/util.c b/builtins/util.c
index 4f108f04..20f60c01 100644
--- a/builtins/util.c
+++ b/builtins/util.c
@@ -12,6 +12,7 @@
public bool USE_COLOR;
+__attribute__((format(printf, 1, 2)))
public char *heap_strf(const char *fmt, ...)
{
va_list args;
@@ -58,6 +59,7 @@ public char *mangle(const char *name)
return mangled;
}
+__attribute__((format(printf, 1, 2)))
public CORD CORD_asprintf(CORD fmt, ...)
{
va_list args;
@@ -72,6 +74,7 @@ public CORD CORD_quoted(CORD str)
{
CORD quoted = "\"";
CORD_pos i;
+#pragma GCC diagnostic ignored "-Wsign-conversion"
CORD_FOR(i, str) {
char c = CORD_pos_fetch(i);
switch (c) {
diff --git a/builtins/util.h b/builtins/util.h
index a3f5f2b4..01f9b269 100644
--- a/builtins/util.h
+++ b/builtins/util.h
@@ -27,9 +27,19 @@
#define public __attribute__ ((visibility ("default")))
#endif
+#ifndef PUREFUNC
+#define PUREFUNC __attribute__ ((pure))
+#endif
+
+#ifndef CONSTFUNC
+#define CONSTFUNC __attribute__ ((const))
+#endif
+
extern bool USE_COLOR;
+__attribute__((format(printf, 1, 2)))
char *heap_strf(const char *fmt, ...);
+__attribute__((format(printf, 1, 2)))
CORD CORD_asprintf(CORD fmt, ...);
CORD CORD_quoted(CORD str);
CORD CORD_replace(CORD c, CORD to_replace, CORD replacement);