mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
committed by
GitHub
parent
82c3facb65
commit
4c1edfb941
@@ -7,142 +7,141 @@
|
||||
**/
|
||||
module std::collections::enumset<Enum>;
|
||||
|
||||
def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private ;
|
||||
|
||||
const IS_CHAR_ARRAY = Enum.elements > 128;
|
||||
|
||||
$switch
|
||||
|
||||
$case (Enum.elements > 128):
|
||||
def EnumSetType @private = char[(Enum.elements + 7) / 8];
|
||||
|
||||
$case (Enum.elements > 64):
|
||||
def EnumSetType @private = uint128;
|
||||
|
||||
$case (Enum.elements > 32 || $$C_INT_SIZE > 32):
|
||||
def EnumSetType @private = ulong;
|
||||
|
||||
$case (Enum.elements > 16 || $$C_INT_SIZE > 16):
|
||||
def EnumSetType @private = uint;
|
||||
|
||||
$case (Enum.elements > 8 || $$C_INT_SIZE > 8):
|
||||
def EnumSetType @private = ushort;
|
||||
|
||||
$default:
|
||||
def EnumSetType @private = char;
|
||||
|
||||
$endswitch
|
||||
|
||||
def EnumSet = distinct EnumSetType;
|
||||
|
||||
|
||||
fn void EnumSet.add(EnumSet* this, Enum v)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
(*this)[v / 8] |= (char)(1u << (v % 8));
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this | 1u << (EnumSetType)v);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
(*this)[(usz)v / 8] |= (char)(1u << ((usz)v % 8));
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this | 1u << (EnumSetType)v);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void EnumSet.clear(EnumSet* this)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
*this = {};
|
||||
$else
|
||||
*this = 0;
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
*this = {};
|
||||
$else
|
||||
*this = 0;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool EnumSet.remove(EnumSet* this, Enum v)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
if (!this.has(v) @inline) return false;
|
||||
(*this)[v / 8] &= (char)~(1 << (v % 8));
|
||||
return true;
|
||||
$else
|
||||
EnumSetType old = (EnumSetType)*this;
|
||||
EnumSetType new = old & ~(1u << (EnumSetType)v);
|
||||
*this = (EnumSet)new;
|
||||
return old != new;
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
if (!this.has(v) @inline) return false;
|
||||
(*this)[(usz)v / 8] &= (char)~(1u << ((usz)v % 8));
|
||||
return true;
|
||||
$else
|
||||
EnumSetType old = (EnumSetType)*this;
|
||||
EnumSetType new = old & ~(1u << (EnumSetType)v);
|
||||
*this = (EnumSet)new;
|
||||
return old != new;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool EnumSet.has(EnumSet* this, Enum v)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
return (bool)(((*this)[v / 8] << (v % 8)) & 0x01);
|
||||
$else
|
||||
return ((EnumSetType)*this & (1u << (EnumSetType)v)) != 0;
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
return (bool)(((*this)[(usz)v / 8] << ((usz)v % 8)) & 0x01);
|
||||
$else
|
||||
return ((EnumSetType)*this & (1u << (EnumSetType)v)) != 0;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void EnumSet.add_all(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] |= c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this | (EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] |= c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this | (EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void EnumSet.retain_all(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] &= c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this & (EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] &= c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this & (EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void EnumSet.remove_all(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] &= ~c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
foreach (i, c : s) (*this)[i] &= ~c;
|
||||
$else
|
||||
*this = (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn EnumSet EnumSet.and_of(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.retain_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this & (EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.retain_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this & (EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn EnumSet EnumSet.or_of(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.add_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this | (EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.add_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this | (EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
fn EnumSet EnumSet.diff_of(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.remove_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
copy.remove_all(s);
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn EnumSet EnumSet.xor_of(EnumSet* this, EnumSet s)
|
||||
{
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
foreach (i, c : s) copy[i] ^= c;
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this ^ (EnumSetType)s);
|
||||
$endif
|
||||
$if IS_CHAR_ARRAY:
|
||||
EnumSet copy = *this;
|
||||
foreach (i, c : s) copy[i] ^= c;
|
||||
return copy;
|
||||
$else
|
||||
return (EnumSet)((EnumSetType)*this ^ (EnumSetType)s);
|
||||
$endif
|
||||
}
|
||||
|
||||
module std::collections::enumset::private;
|
||||
|
||||
macro typeid type_for_enum_elements(usz $elements)
|
||||
{
|
||||
$switch
|
||||
$case ($elements > 128):
|
||||
return char[($elements + 7) / 8].typeid;
|
||||
$case ($elements > 64):
|
||||
return uint128.typeid;
|
||||
$case ($elements > 32 || $$C_INT_SIZE > 32):
|
||||
return ulong.typeid;
|
||||
$case ($elements > 16 || $$C_INT_SIZE > 16):
|
||||
return uint.typeid;
|
||||
$case ($elements > 8 || $$C_INT_SIZE > 8):
|
||||
return ushort.typeid;
|
||||
$default:
|
||||
return char.typeid;
|
||||
$endswitch;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ module std::collections::list<Type>;
|
||||
import std::math;
|
||||
|
||||
def ElementPredicate = fn bool(Type *type);
|
||||
const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type);
|
||||
const ELEMENT_IS_POINTER = Type.kindof == POINTER;
|
||||
|
||||
struct List
|
||||
{
|
||||
@@ -38,24 +40,28 @@ fn void List.tinit(List* list, usz initial_capacity = 16)
|
||||
list.init(initial_capacity, mem::temp()) @inline;
|
||||
}
|
||||
|
||||
fn void! List.to_format(List* list, Formatter* formatter) @dynamic
|
||||
{
|
||||
switch (list.size)
|
||||
{
|
||||
case 0:
|
||||
formatter.print("[]")!;
|
||||
case 1:
|
||||
formatter.printf("[%s]", list.entries[0])!;
|
||||
default:
|
||||
formatter.print("[")!;
|
||||
foreach (i, element : list.entries[:list.size])
|
||||
{
|
||||
if (i != 0) formatter.print(", ")!;
|
||||
formatter.printf("%s", element)!;
|
||||
}
|
||||
formatter.print("]")!;
|
||||
}
|
||||
}
|
||||
|
||||
fn String List.to_string(List* list, Allocator* using = mem::heap()) @dynamic
|
||||
{
|
||||
if (!list.size) return "[]".copy(using);
|
||||
if (list.size == 1) return string::printf("[%s]", list.entries[0], .using = using);
|
||||
|
||||
@stack_mem(512 + 128; Allocator* mem)
|
||||
{
|
||||
DString str;
|
||||
str.init(512, mem);
|
||||
str.append("[");
|
||||
foreach (i, element : list.entries[:list.size])
|
||||
{
|
||||
if (i != 0) str.append(", ");
|
||||
str.printf("%s", element);
|
||||
}
|
||||
str.printf("]");
|
||||
return str.copy_str(using);
|
||||
};
|
||||
return string::printf("%s", *list);
|
||||
}
|
||||
|
||||
fn void List.push(List* list, Type element) @inline
|
||||
@@ -301,9 +307,8 @@ fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
|
||||
|
||||
// Functions for equatable types
|
||||
|
||||
$if types::is_equatable_type(Type):
|
||||
|
||||
fn usz! List.index_of(List* list, Type type)
|
||||
fn usz! List.index_of(List* list, Type type) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
foreach (i, v : list)
|
||||
{
|
||||
@@ -312,7 +317,7 @@ fn usz! List.index_of(List* list, Type type)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn usz! List.rindex_of(List* list, Type type)
|
||||
fn usz! List.rindex_of(List* list, Type type) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
foreach_r (i, v : list)
|
||||
{
|
||||
@@ -321,7 +326,7 @@ fn usz! List.rindex_of(List* list, Type type)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn bool List.equals(List* list, List other_list)
|
||||
fn bool List.equals(List* list, List other_list) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
if (list.size != other_list.size) return false;
|
||||
foreach (i, v : list)
|
||||
@@ -338,7 +343,7 @@ fn bool List.equals(List* list, List other_list)
|
||||
* @param value "The value to search for"
|
||||
* @return "True if the value is found, false otherwise"
|
||||
**/
|
||||
fn bool List.contains(List* list, Type value)
|
||||
fn bool List.contains(List* list, Type value) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
foreach (i, v : list)
|
||||
{
|
||||
@@ -353,7 +358,7 @@ fn bool List.contains(List* list, Type value)
|
||||
* @param value "The value to remove"
|
||||
* @return "the number of deleted elements."
|
||||
**/
|
||||
fn usz List.remove(List* list, Type value)
|
||||
fn usz List.remove(List* list, Type value) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
@@ -368,29 +373,24 @@ fn usz List.remove(List* list, Type value)
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
fn void List.remove_all(List* list, List* other_list)
|
||||
fn void List.remove_all(List* list, List* other_list) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
if (!other_list.size) return;
|
||||
foreach (v : other_list) list.remove(v);
|
||||
}
|
||||
|
||||
|
||||
$endif
|
||||
|
||||
$if Type.kindof == POINTER:
|
||||
|
||||
/**
|
||||
* @param [&in] list
|
||||
* @return "The number non-null values in the list"
|
||||
**/
|
||||
fn usz List.compact_count(List* list)
|
||||
fn usz List.compact_count(List* list) @if(ELEMENT_IS_POINTER)
|
||||
{
|
||||
usz vals = 0;
|
||||
foreach (v : list) if (v) vals++;
|
||||
return vals;
|
||||
}
|
||||
|
||||
fn usz List.compact(List* list)
|
||||
fn usz List.compact(List* list) @if(ELEMENT_IS_POINTER)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
@@ -404,5 +404,3 @@ fn usz List.compact(List* list)
|
||||
}
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -7,7 +7,7 @@ import std::math;
|
||||
const uint DEFAULT_INITIAL_CAPACITY = 16;
|
||||
const uint MAXIMUM_CAPACITY = 1u << 31;
|
||||
const float DEFAULT_LOAD_FACTOR = 0.75;
|
||||
|
||||
const VALUE_IS_EQUATABLE = types::is_equatable(Value);
|
||||
|
||||
struct HashMap
|
||||
{
|
||||
@@ -216,8 +216,7 @@ fn Value[] HashMap.value_list(HashMap* map, Allocator* using = mem::heap())
|
||||
return list;
|
||||
}
|
||||
|
||||
$if types::is_equatable(Value):
|
||||
fn bool HashMap.has_value(HashMap* map, Value v)
|
||||
fn bool HashMap.has_value(HashMap* map, Value v) @if(VALUE_IS_EQUATABLE)
|
||||
{
|
||||
if (!map.count) return false;
|
||||
foreach (Entry* entry : map.table)
|
||||
@@ -230,7 +229,6 @@ fn bool HashMap.has_value(HashMap* map, Value v)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$endif
|
||||
|
||||
// --- private methods
|
||||
|
||||
|
||||
@@ -209,25 +209,25 @@ macro Object* object_from_value(value) @private
|
||||
{
|
||||
var $Type = $typeof(value);
|
||||
|
||||
$switch
|
||||
$case types::is_int($Type):
|
||||
return new_int(value);
|
||||
$case types::is_float($Type):
|
||||
return new_float(value);
|
||||
$case $Type.typeid == String.typeid:
|
||||
return new_string(value);
|
||||
$case $Type.typeid == bool.typeid:
|
||||
return new_bool(value);
|
||||
$case $Type.typeid == Object*.typeid:
|
||||
return value;
|
||||
$case $Type.typeid == void*.typeid:
|
||||
assert(value == null);
|
||||
return &NULL_OBJECT;
|
||||
$case $checks(String s = value):
|
||||
return new_string(value);
|
||||
$default:
|
||||
$error "Unsupported object type.";
|
||||
$endswitch
|
||||
$switch
|
||||
$case types::is_int($Type):
|
||||
return new_int(value);
|
||||
$case types::is_float($Type):
|
||||
return new_float(value);
|
||||
$case $Type.typeid == String.typeid:
|
||||
return new_string(value);
|
||||
$case $Type.typeid == bool.typeid:
|
||||
return new_bool(value);
|
||||
$case $Type.typeid == Object*.typeid:
|
||||
return value;
|
||||
$case $Type.typeid == void*.typeid:
|
||||
assert(value == null);
|
||||
return &NULL_OBJECT;
|
||||
$case $checks(String s = value):
|
||||
return new_string(value);
|
||||
$default:
|
||||
$error "Unsupported object type.";
|
||||
$endswitch
|
||||
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ fn Object* Object.get_or_create_obj(Object* o, String key)
|
||||
return container;
|
||||
}
|
||||
|
||||
def ObjectInternalMap @private = HashMap<String, Object*>;
|
||||
def ObjectInternalList @private = List<Object*>;
|
||||
def ObjectInternalMapEntry @private = Entry<String, Object*>;
|
||||
def ObjectInternalMap = HashMap<String, Object*> @private;
|
||||
def ObjectInternalList = List<Object*> @private;
|
||||
def ObjectInternalMapEntry = Entry<String, Object*> @private;
|
||||
|
||||
|
||||
@@ -181,11 +181,11 @@ macro enum_by_name($Type, String enum_name) @builtin
|
||||
**/
|
||||
macro bool @likely(bool #value, $probability = 1.0) @builtin
|
||||
{
|
||||
$if $probability == 1.0:
|
||||
return $$expect(#value, true);
|
||||
$else
|
||||
return $$expect_with_probability(#value, true, $probability);
|
||||
$endif
|
||||
$if $probability == 1.0:
|
||||
return $$expect(#value, true);
|
||||
$else
|
||||
return $$expect_with_probability(#value, true, $probability);
|
||||
$endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,11 +197,11 @@ $endif
|
||||
**/
|
||||
macro bool @unlikely(bool #value, $probability = 1.0) @builtin
|
||||
{
|
||||
$if $probability == 1.0:
|
||||
return $$expect(#value, false);
|
||||
$else
|
||||
return $$expect_with_probability(#value, false, $probability);
|
||||
$endif
|
||||
$if $probability == 1.0:
|
||||
return $$expect(#value, false);
|
||||
$else
|
||||
return $$expect_with_probability(#value, false, $probability);
|
||||
$endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,9 +212,9 @@ $endif
|
||||
macro @expect(#value, expected, $probability = 1.0) @builtin
|
||||
{
|
||||
$if $probability == 1.0:
|
||||
return $$expect(#value, ($typeof(#value))expected);
|
||||
return $$expect(#value, ($typeof(#value))expected);
|
||||
$else
|
||||
return $$expect_with_probability(#value, expected, $probability);
|
||||
return $$expect_with_probability(#value, expected, $probability);
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ module std::core::builtin;
|
||||
**/
|
||||
macro less(a, b) @builtin
|
||||
{
|
||||
$switch
|
||||
$switch
|
||||
$case $defined(a.less):
|
||||
return a.less(b);
|
||||
$case $defined(a.compare_to):
|
||||
return a.compare_to(b) < 0;
|
||||
$default:
|
||||
return a < b;
|
||||
$endswitch
|
||||
$endswitch
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,14 +23,14 @@ $endswitch
|
||||
**/
|
||||
macro less_eq(a, b) @builtin
|
||||
{
|
||||
$switch
|
||||
$switch
|
||||
$case $defined(a.less):
|
||||
return !b.less(a);
|
||||
$case $defined(a.compare_to):
|
||||
return a.compare_to(b) <= 0;
|
||||
$default:
|
||||
return a <= b;
|
||||
$endswitch
|
||||
$endswitch
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,14 +38,14 @@ $endswitch
|
||||
**/
|
||||
macro greater(a, b) @builtin
|
||||
{
|
||||
$switch
|
||||
$switch
|
||||
$case $defined(a.less):
|
||||
return b.less(a);
|
||||
$case $defined(a.compare_to):
|
||||
return a.compare_to(b) > 0;
|
||||
$default:
|
||||
return a > b;
|
||||
$endswitch
|
||||
$endswitch
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,14 +53,14 @@ $endswitch
|
||||
**/
|
||||
macro greater_eq(a, b) @builtin
|
||||
{
|
||||
$switch
|
||||
$switch
|
||||
$case $defined(a.less):
|
||||
return !a.less(b);
|
||||
$case $defined(a.compare_to):
|
||||
return a.compare_to(b) >= 0;
|
||||
$default:
|
||||
return a >= b;
|
||||
$endswitch
|
||||
$endswitch
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ $endswitch
|
||||
**/
|
||||
macro bool equals(a, b) @builtin
|
||||
{
|
||||
$switch
|
||||
$switch
|
||||
$case $defined(a.equals):
|
||||
return a.equals(b);
|
||||
$case $defined(a.compare_to):
|
||||
@@ -77,7 +77,7 @@ $switch
|
||||
return !a.less(b) && !b.less(a);
|
||||
$default:
|
||||
return a == b;
|
||||
$endswitch
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro min(x, ...) @builtin
|
||||
|
||||
@@ -16,72 +16,40 @@ $assert C_SHORT_SIZE <= C_INT_SIZE;
|
||||
$assert C_INT_SIZE <= C_LONG_SIZE;
|
||||
$assert C_LONG_SIZE <= C_LONG_LONG_SIZE;
|
||||
|
||||
$switch ($$C_INT_SIZE)
|
||||
$case 64:
|
||||
def CInt = long;
|
||||
def CUInt = ulong;
|
||||
$case 32:
|
||||
def CInt = int;
|
||||
def CUInt = uint;
|
||||
$case 16:
|
||||
def CInt = short;
|
||||
def CUInt = ushort;
|
||||
$default:
|
||||
$error "Invalid C int size";
|
||||
$endswitch
|
||||
|
||||
$switch ($$C_LONG_SIZE)
|
||||
$case 64:
|
||||
def CLong = long;
|
||||
def CULong = ulong;
|
||||
$case 32:
|
||||
def CLong = int;
|
||||
def CULong = uint;
|
||||
$case 16:
|
||||
def CLong = short;
|
||||
def CULong = ushort;
|
||||
$default:
|
||||
$error "Invalid C long size";
|
||||
$endswitch
|
||||
|
||||
$switch ($$C_SHORT_SIZE)
|
||||
$case 32:
|
||||
def CShort = int;
|
||||
def CUShort = uint;
|
||||
$case 16:
|
||||
def CShort = short;
|
||||
def CUShort = ushort;
|
||||
$case 8:
|
||||
def CShort = ichar;
|
||||
def CUShort = char;
|
||||
$default:
|
||||
$error "Invalid C short size";
|
||||
$endswitch
|
||||
|
||||
$switch ($$C_LONG_LONG_SIZE)
|
||||
$case 128:
|
||||
def CLongLong = int128;
|
||||
def CULongLong = uint128;
|
||||
$case 64:
|
||||
def CLongLong = long;
|
||||
def CULongLong = ulong;
|
||||
$case 32:
|
||||
def CLongLong = int;
|
||||
def CULongLong = uint;
|
||||
$case 16:
|
||||
def CLongLong = short;
|
||||
def CULongLong = ushort;
|
||||
$default:
|
||||
$error "Invalid C long long size";
|
||||
$endswitch
|
||||
|
||||
|
||||
|
||||
def CShort = $typefrom(signed_int_from_bitsize($$C_SHORT_SIZE));
|
||||
def CUShort = $typefrom(unsigned_int_from_bitsize($$C_SHORT_SIZE));
|
||||
def CInt = $typefrom(signed_int_from_bitsize($$C_INT_SIZE));
|
||||
def CUInt = $typefrom(unsigned_int_from_bitsize($$C_INT_SIZE));
|
||||
def CLong = $typefrom(signed_int_from_bitsize($$C_LONG_SIZE));
|
||||
def CULong = $typefrom(unsigned_int_from_bitsize($$C_LONG_SIZE));
|
||||
def CLongLong = $typefrom(signed_int_from_bitsize($$C_LONG_LONG_SIZE));
|
||||
def CULongLong = $typefrom(unsigned_int_from_bitsize($$C_LONG_LONG_SIZE));
|
||||
def CSChar = ichar;
|
||||
def CUChar = char;
|
||||
|
||||
$if $$C_CHAR_IS_SIGNED:
|
||||
def CChar = ichar;
|
||||
$else
|
||||
def CChar = char;
|
||||
$endif
|
||||
def CChar = $typefrom($$C_CHAR_IS_SIGNED ? ichar.typeid : char.typeid);
|
||||
|
||||
// Helper macros
|
||||
macro typeid signed_int_from_bitsize(usz $bitsize) @private
|
||||
{
|
||||
$switch ($bitsize)
|
||||
$case 128: return int128.typeid;
|
||||
$case 64: return long.typeid;
|
||||
$case 32: return int.typeid;
|
||||
$case 16: return short.typeid;
|
||||
$case 8: return ichar.typeid;
|
||||
$default: $error("Invalid bitsize");
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro typeid unsigned_int_from_bitsize(usz $bitsize) @private
|
||||
{
|
||||
$switch ($bitsize)
|
||||
$case 128: return uint128.typeid;
|
||||
$case 64: return ulong.typeid;
|
||||
$case 32: return uint.typeid;
|
||||
$case 16: return ushort.typeid;
|
||||
$case 8: return char.typeid;
|
||||
$default: $error("Invalid bitsize");
|
||||
$endswitch
|
||||
}
|
||||
|
||||
@@ -128,6 +128,22 @@ const bool BENCHMARKING = $$BENCHMARKING;
|
||||
const bool TESTING = $$TESTING;
|
||||
const MemoryEnvironment MEMORY_ENV = (MemoryEnvironment)$$MEMORY_ENVIRONMENT;
|
||||
|
||||
const LINUX_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX;
|
||||
const DARWIN_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_darwin();
|
||||
const WIN32_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_win32();
|
||||
const POSIX_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_posix();
|
||||
const OPENBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OPENBSD;
|
||||
const FREEBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == FREEBSD;
|
||||
const NETBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == NETBSD;
|
||||
const WASI_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == WASI;
|
||||
const WASM_NOLIBC @builtin = !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64;
|
||||
const bool NO_LIBC = !env::COMPILER_LIBC_AVAILABLE;
|
||||
const bool WIN32 = OS_TYPE == WIN32;
|
||||
const bool DARWIN = OS_TYPE == IOS || OS_TYPE == MACOS || OS_TYPE == TVOS || OS_TYPE == WATCHOS;
|
||||
const bool LINUX = OS_TYPE == LINUX;
|
||||
const bool POSIX = os_is_posix();
|
||||
const bool WASI = OS_TYPE == WASI;
|
||||
|
||||
macro bool os_is_win32()
|
||||
{
|
||||
return OS_TYPE == WIN32;
|
||||
@@ -177,15 +193,15 @@ macro bool os_is_posix()
|
||||
**/
|
||||
fn String! get_var(String name)
|
||||
{
|
||||
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
|
||||
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
ZString val = libc::getenv(name.zstr_tcopy());
|
||||
return val ? val.as_str() : SearchResult.MISSING?;
|
||||
};
|
||||
$else
|
||||
$else
|
||||
return "";
|
||||
$endif
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +212,7 @@ $endif
|
||||
**/
|
||||
fn void set_var(String name, String value, bool overwrite = true)
|
||||
{
|
||||
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
|
||||
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
if (libc::setenv(name.zstr_tcopy(), value.zstr_copy(), (int)overwrite))
|
||||
@@ -204,7 +220,7 @@ $if COMPILER_LIBC_AVAILABLE && !os_is_win32():
|
||||
unreachable();
|
||||
}
|
||||
};
|
||||
$endif
|
||||
$endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +229,7 @@ $endif
|
||||
**/
|
||||
fn void clear_var(String name)
|
||||
{
|
||||
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
|
||||
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
if (libc::unsetenv(name.zstr_tcopy()))
|
||||
@@ -221,6 +237,6 @@ $if COMPILER_LIBC_AVAILABLE && !os_is_win32():
|
||||
unreachable();
|
||||
}
|
||||
};
|
||||
$endif
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
@@ -411,10 +411,10 @@ macro TempAllocator* temp()
|
||||
macro Allocator* current_allocator() => thread_allocator;
|
||||
macro Allocator* heap() => thread_allocator;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64:
|
||||
|
||||
module std::core::mem @if(WASM_NOLIBC);
|
||||
|
||||
SimpleHeapAllocator wasm_allocator @private;
|
||||
|
||||
extern int __heap_base;
|
||||
|
||||
static initialize @priority(1)
|
||||
@@ -425,7 +425,4 @@ static initialize @priority(1)
|
||||
if (start > mem::DEFAULT_MEM_ALIGNMENT) allocator::wasm_memory.use = start;
|
||||
wasm_allocator.init(fn (x) => allocator::wasm_memory.allocate_block(x));
|
||||
thread_allocator = &wasm_allocator;
|
||||
}
|
||||
$endif
|
||||
|
||||
|
||||
}
|
||||
@@ -55,7 +55,7 @@ macro int @main_to_void_main_args(#m, int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
$if env::os_is_win32():
|
||||
module std::core::main_stub @if(env::os_is_win32());
|
||||
|
||||
extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW");
|
||||
|
||||
@@ -164,5 +164,3 @@ macro int @wmain_to_void_main_args(#m, int argc, Char16** argv)
|
||||
#m(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -88,12 +88,12 @@ fn bool __run_default_test_runner()
|
||||
return test_runner_create().run();
|
||||
}
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64:
|
||||
|
||||
module std::core::runtime @if(WASM_NOLIBC);
|
||||
|
||||
extern fn void __wasm_call_ctors();
|
||||
fn void wasm_initialize() @extern("_initialize") @wasm
|
||||
{
|
||||
// The linker synthesizes this to call constructors.
|
||||
__wasm_call_ctors();
|
||||
}
|
||||
$endif
|
||||
}
|
||||
@@ -96,12 +96,12 @@ macro @blk(&block, i) @local
|
||||
|
||||
macro @blk0(&block, i) @local
|
||||
{
|
||||
$if env::BIG_ENDIAN:
|
||||
return block.l[i];
|
||||
$else
|
||||
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
|
||||
| (block.l[i].rotl(8) & 0x00FF00FF);
|
||||
$endif
|
||||
$if env::BIG_ENDIAN:
|
||||
return block.l[i];
|
||||
$else
|
||||
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
|
||||
| (block.l[i].rotl(8) & 0x00FF00FF);
|
||||
$endif
|
||||
}
|
||||
|
||||
macro @r0(&block, v, &w, x, y, &z, i) @local
|
||||
|
||||
@@ -144,6 +144,7 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
fn void! Formatter.out_str(Formatter* this, any arg) @private
|
||||
{
|
||||
switch (arg.type.kindof)
|
||||
@@ -425,3 +426,18 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys)
|
||||
return this.idx;
|
||||
}
|
||||
|
||||
|
||||
fn usz! Formatter.print(Formatter* this, String str)
|
||||
{
|
||||
if (!this.out_fn)
|
||||
{
|
||||
// use null output function
|
||||
this.out_fn = &out_null_fn;
|
||||
}
|
||||
usz len = str.len;
|
||||
for (usz i = 0; i < len; i++)
|
||||
{
|
||||
this.out(str[i])!;
|
||||
}
|
||||
return this.idx;
|
||||
}
|
||||
|
||||
@@ -169,21 +169,21 @@ fn usz! Stream.copy_to(Stream* s, Stream* dst, char[] buffer = {})
|
||||
if (buffer.len) return copy_through_buffer(s, dst, buffer);
|
||||
if (WriteToStreamFn func = s.fns.write_stream_fn) return func(s, dst);
|
||||
if (ReadFromStreamFn func = dst.fns.read_stream_fn) return func(dst, s);
|
||||
$switch (env::MEMORY_ENV)
|
||||
$case NORMAL:
|
||||
@pool()
|
||||
{
|
||||
return copy_through_buffer(s, dst, tmalloc(char, 4096));
|
||||
};
|
||||
$case SMALL:
|
||||
@pool()
|
||||
{
|
||||
return copy_through_buffer(s, dst, tmalloc(char, 1024));
|
||||
};
|
||||
$case TINY:
|
||||
$case NONE:
|
||||
return copy_through_buffer(s, dst, &&(char[256]{}));
|
||||
$endswitch
|
||||
$switch (env::MEMORY_ENV)
|
||||
$case NORMAL:
|
||||
@pool()
|
||||
{
|
||||
return copy_through_buffer(s, dst, tmalloc(char, 4096));
|
||||
};
|
||||
$case SMALL:
|
||||
@pool()
|
||||
{
|
||||
return copy_through_buffer(s, dst, tmalloc(char, 1024));
|
||||
};
|
||||
$case TINY:
|
||||
$case NONE:
|
||||
return copy_through_buffer(s, dst, &&(char[256]{}));
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro usz! copy_through_buffer(Stream* s, Stream* dst, char[] buffer) @local
|
||||
|
||||
@@ -1,44 +1,30 @@
|
||||
module std::io::os;
|
||||
import libc;
|
||||
|
||||
|
||||
$switch
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
|
||||
|
||||
macro void! native_chdir(Path p)
|
||||
{
|
||||
if (posix::chdir(p.as_zstr()))
|
||||
{
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EACCES: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::ENOTDIR: return IoError.FILE_NOT_DIR?;
|
||||
case errno::ENOENT: return IoError.FILE_NOT_FOUND?;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
|
||||
macro void! native_chdir(Path path)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
// TODO improve with better error handling.
|
||||
if (win32::win32_SetCurrentDirectoryW(path.as_str().to_temp_utf16()!!)) return;
|
||||
};
|
||||
return IoError.GENERAL_ERROR?;
|
||||
$switch
|
||||
$case POSIX_LIBC:
|
||||
if (posix::chdir(path.as_zstr()))
|
||||
{
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EACCES: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::ENOTDIR: return IoError.FILE_NOT_DIR?;
|
||||
case errno::ENOENT: return IoError.FILE_NOT_FOUND?;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
}
|
||||
$case WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
// TODO improve with better error handling.
|
||||
if (win32::win32_SetCurrentDirectoryW(path.as_str().to_temp_utf16()!!)) return;
|
||||
};
|
||||
return IoError.GENERAL_ERROR?;
|
||||
$default:
|
||||
unreachable("'getcwd' not available");
|
||||
$endswitch
|
||||
}
|
||||
|
||||
$default:
|
||||
|
||||
fn void! native_chdir(Path path)
|
||||
{
|
||||
unreachable("'getcwd' not available");
|
||||
}
|
||||
|
||||
$endswitch
|
||||
@@ -9,28 +9,13 @@ def FtellFn = fn usz!(void*);
|
||||
def FwriteFn = fn usz!(void*, char[] buffer);
|
||||
def FreadFn = fn usz!(void*, char[] buffer);
|
||||
|
||||
$if !$defined(native_fopen_fn):
|
||||
FopenFn native_fopen_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_fclose_fn):
|
||||
FcloseFn native_fclose_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_freopen_fn):
|
||||
FreopenFn native_freopen_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_fseek_fn):
|
||||
FseekFn native_fseek_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_ftell_fn):
|
||||
FtellFn native_ftell_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_fwrite_fn):
|
||||
FwriteFn native_fwrite_fn @weak;
|
||||
$endif
|
||||
$if !$defined(native_fread_fn):
|
||||
FreadFn native_fread_fn @weak;
|
||||
$endif
|
||||
|
||||
FopenFn native_fopen_fn @weak @if(!$defined(native_fopen_fn));
|
||||
FcloseFn native_fclose_fn @weak @if(!$defined(native_fclose_fn));
|
||||
FreopenFn native_freopen_fn @weak @if(!$defined(native_freopen_fn));
|
||||
FseekFn native_fseek_fn @weak @if(!$defined(native_fseek_fn));
|
||||
FtellFn native_ftell_fn @weak @if(!$defined(native_ftell_fn));
|
||||
FwriteFn native_fwrite_fn @weak @if(!$defined(native_fwrite_fn));
|
||||
FreadFn native_fread_fn @weak @if(!$defined(native_fread_fn));
|
||||
|
||||
/**
|
||||
* @require mode.len > 0
|
||||
@@ -38,20 +23,20 @@ $endif
|
||||
**/
|
||||
fn void*! native_fopen(String filename, String mode) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fopen_fn) return native_fopen_fn(filename, mode);
|
||||
unreachable("Tried to call fopen without support.");
|
||||
$else
|
||||
@pool()
|
||||
{
|
||||
$if env::os_is_win32():
|
||||
void* file = (CFile)_wfopen(filename.to_temp_utf16(), filename.to_temp_utf16())!;
|
||||
$else
|
||||
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
|
||||
@pool()
|
||||
{
|
||||
$if env::os_is_win32():
|
||||
void* file = (CFile)_wfopen(filename.to_temp_utf16(), filename.to_temp_utf16())!;
|
||||
$else
|
||||
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
|
||||
$endif
|
||||
return file ?: file_open_errno()?;
|
||||
};
|
||||
$endif
|
||||
return file ?: file_open_errno()?;
|
||||
};
|
||||
$endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,71 +45,71 @@ $endif
|
||||
**/
|
||||
fn void*! native_freopen(void* file, String filename, String mode) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_freopen_fn) return native_freopen_fn(file, filename, mode);
|
||||
unreachable("Tried to call freopen without support.");
|
||||
$else
|
||||
@pool()
|
||||
{
|
||||
$if env::os_is_win32():
|
||||
file = _wfreopen(filename.to_temp_utf16(), mode.to_temp_utf16(), file)!;
|
||||
$else
|
||||
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
|
||||
@pool()
|
||||
{
|
||||
$if env::os_is_win32():
|
||||
file = _wfreopen(filename.to_temp_utf16(), mode.to_temp_utf16(), file)!;
|
||||
$else
|
||||
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
|
||||
$endif
|
||||
return file ?: file_open_errno()?;
|
||||
};
|
||||
$endif
|
||||
return file ?: file_open_errno()?;
|
||||
};
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void! native_fseek(void* file, isz offset, Seek seek_mode) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
|
||||
unreachable("Tried to call fseek without support.");
|
||||
$else
|
||||
$if env::os_is_win32():
|
||||
bool success = _fseeki64(file, (long)offset, (int)seek_mode) == 0;
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
|
||||
unreachable("Tried to call fseek without support.");
|
||||
$else
|
||||
bool success = libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode) == 0;
|
||||
$if env::os_is_win32():
|
||||
bool success = _fseeki64(file, (long)offset, (int)seek_mode) == 0;
|
||||
$else
|
||||
bool success = libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode) == 0;
|
||||
$endif
|
||||
if (!success) return file_seek_errno()?;
|
||||
$endif
|
||||
if (!success) return file_seek_errno()?;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn usz! native_ftell(CFile file) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_ftell_fn) return native_ftell_fn(file);
|
||||
unreachable("Tried to call ftell without support.");
|
||||
$else
|
||||
$if env::os_is_win32():
|
||||
long index = _ftelli64(file);
|
||||
return index >= 0 ? index : file_seek_errno()?;
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_ftell_fn) return native_ftell_fn(file);
|
||||
unreachable("Tried to call ftell without support.");
|
||||
$else
|
||||
SeekIndex index = libc::ftell(file);
|
||||
return index >= 0 ? index : file_seek_errno()?;
|
||||
$if env::os_is_win32():
|
||||
long index = _ftelli64(file);
|
||||
return index >= 0 ? index : file_seek_errno()?;
|
||||
$else
|
||||
SeekIndex index = libc::ftell(file);
|
||||
return index >= 0 ? index : file_seek_errno()?;
|
||||
$endif
|
||||
$endif
|
||||
$endif
|
||||
}
|
||||
|
||||
fn usz! native_fwrite(CFile file, char[] buffer) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
|
||||
unreachable("Tried to call fwrite without support.");
|
||||
$else
|
||||
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
|
||||
$endif
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
|
||||
unreachable("Tried to call fwrite without support.");
|
||||
$else
|
||||
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
|
||||
$endif
|
||||
}
|
||||
|
||||
fn usz! native_fread(CFile file, char[] buffer) @inline
|
||||
{
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fread_fn) return native_fread_fn(file, buffer);
|
||||
unreachable("Tried to call fread without support.");
|
||||
$else
|
||||
return libc::fread(buffer.ptr, 1, buffer.len, file);
|
||||
$endif
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
if (native_fread_fn) return native_fread_fn(file, buffer);
|
||||
unreachable("Tried to call fread without support.");
|
||||
$else
|
||||
return libc::fread(buffer.ptr, 1, buffer.len, file);
|
||||
$endif
|
||||
}
|
||||
|
||||
macro anyfault file_open_errno() @local
|
||||
@@ -175,13 +160,10 @@ macro anyfault file_seek_errno() @local
|
||||
}
|
||||
|
||||
// Win functions
|
||||
$if env::os_is_win32():
|
||||
extern fn void* _wfopen(Char16*, Char16*) @local;
|
||||
extern fn void* _wfreopen(Char16*, Char16*, CFile) @local;
|
||||
extern fn int _fseeki64(CFile, long, int) @local;
|
||||
extern fn long _ftelli64(CFile) @local;
|
||||
$endif
|
||||
extern fn void* _wfopen(Char16*, Char16*) @local @if(WIN32_LIBC);
|
||||
extern fn void* _wfreopen(Char16*, Char16*, CFile) @local @if(WIN32_LIBC);
|
||||
extern fn int _fseeki64(CFile, long, int) @local @if(WIN32_LIBC);
|
||||
extern fn long _ftelli64(CFile) @local @if(WIN32_LIBC);
|
||||
|
||||
$if env::os_is_posix():
|
||||
extern fn CInt access(ZString path, CInt mode);
|
||||
$endif
|
||||
// Posix functions
|
||||
extern fn CInt access(ZString path, CInt mode) @if(POSIX_LIBC);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::io::file::os;
|
||||
module std::io::file::os @if(DARWIN_LIBC);
|
||||
import libc;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
|
||||
struct DarwinTimespec @private
|
||||
{
|
||||
long tv_sec;
|
||||
@@ -97,5 +95,4 @@ fn void! read_stat(Darwin64Stat* stat, String path) @local
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
$endif
|
||||
}
|
||||
@@ -1,7 +1,25 @@
|
||||
module std::io::file::os;
|
||||
|
||||
const USE_DARWIN_INODE64 = env::os_is_darwin() && env::ARCH_TYPE == X86_64;
|
||||
|
||||
extern fn NativeDirentry* readdir(void*) @extern("readdir") @if(!USE_DARWIN_INODE64) ;
|
||||
extern fn NativeDirentry* readdir(void*) @extern("readdir$INODE64") @if(USE_DARWIN_INODE64);
|
||||
|
||||
struct NativeDirentry
|
||||
{
|
||||
usz ino;
|
||||
usz seekoff @if(env::os_is_darwin());
|
||||
isz seekoff @if(!env::os_is_darwin());
|
||||
ushort reclen;
|
||||
ushort namelen @if(env::os_is_darwin());
|
||||
char type;
|
||||
char[1024] name @if(env::os_is_darwin());
|
||||
char[*] name @if(!env::os_is_darwin());
|
||||
}
|
||||
|
||||
module std::io::file::os @if(!env::os_is_win32());
|
||||
|
||||
// native_temp_directory, for non Win32
|
||||
$if !env::os_is_win32():
|
||||
|
||||
fn Path! native_temp_directory(Allocator* using = mem::heap())
|
||||
{
|
||||
@@ -13,7 +31,7 @@ fn Path! native_temp_directory(Allocator* using = mem::heap())
|
||||
return path::new("/tmp", using);
|
||||
}
|
||||
|
||||
$if env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::io::file::os @if(env::COMPILER_LIBC_AVAILABLE && !env::os_is_win32());
|
||||
|
||||
extern fn void* opendir(ZString);
|
||||
extern fn void closedir(void*);
|
||||
@@ -80,11 +98,7 @@ fn void! native_rmtree(Path dir)
|
||||
os::native_rmdir(dir)!;
|
||||
}
|
||||
|
||||
$endif
|
||||
|
||||
$endif
|
||||
|
||||
$if !env::os_is_darwin() && !env::os_is_win32():
|
||||
module std::io::file::os @if(!env::os_is_darwin() && !env::os_is_win32());
|
||||
|
||||
fn usz! native_file_size(String path)
|
||||
{
|
||||
@@ -93,89 +107,38 @@ fn usz! native_file_size(String path)
|
||||
return f.seek(0, Seek.END)!;
|
||||
}
|
||||
|
||||
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
|
||||
|
||||
fn bool native_file_or_dir_exists(String path)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
return os::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
|
||||
};
|
||||
$if POSIX_LIBC:
|
||||
@pool()
|
||||
{
|
||||
return os::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
|
||||
};
|
||||
$else
|
||||
unreachable("Tried to call file_or_dir_exists without support.");
|
||||
return false;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool native_is_file(String path)
|
||||
{
|
||||
File! f = file::open(path, "r");
|
||||
defer (void)f.close();
|
||||
return @ok(f);
|
||||
$if POSIX_LIBC:
|
||||
File! f = file::open(path, "r");
|
||||
defer (void)f.close();
|
||||
return @ok(f);
|
||||
$else
|
||||
unreachable("Tried to call is_file without support.");
|
||||
return false;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool native_is_dir(String path)
|
||||
{
|
||||
return native_file_or_dir_exists(path) && !native_is_file(path);
|
||||
$if POSIX_LIBC:
|
||||
return native_file_or_dir_exists(path) && !native_is_file(path);
|
||||
$else
|
||||
unreachable("Tried to call is_dir without support.");
|
||||
return false;
|
||||
$endif
|
||||
}
|
||||
|
||||
$else
|
||||
|
||||
fn bool native_file_or_dir_exists(String path)
|
||||
{
|
||||
unreachable("Tried to call file_or_dir_exists without support.");
|
||||
}
|
||||
|
||||
fn bool native_is_dir(String path)
|
||||
{
|
||||
unreachable("Tried to call is_dir without support.");
|
||||
}
|
||||
|
||||
fn bool native_is_file(String path)
|
||||
{
|
||||
unreachable("Tried to call is_file without support.");
|
||||
}
|
||||
|
||||
$endif
|
||||
|
||||
$endif
|
||||
|
||||
$switch (env::OS_TYPE)
|
||||
$case IOS:
|
||||
$case MACOS:
|
||||
$case TVOS:
|
||||
$case WATCHOS:
|
||||
|
||||
$if env::ARCH_TYPE == X86_64:
|
||||
extern fn NativeDirentry* readdir(void*) @extern("readdir$INODE64");
|
||||
$else
|
||||
extern fn NativeDirentry* readdir(void*) @extern("readdir");
|
||||
$endif
|
||||
|
||||
struct NativeDirentry
|
||||
{
|
||||
usz ino;
|
||||
usz seekoff;
|
||||
ushort reclen;
|
||||
ushort namelen;
|
||||
char type;
|
||||
char[1024] name;
|
||||
}
|
||||
$case LINUX:
|
||||
extern fn NativeDirentry* readdir(void*);
|
||||
struct NativeDirentry
|
||||
{
|
||||
usz ino;
|
||||
isz seekoff;
|
||||
ushort reclen;
|
||||
char type;
|
||||
char[*] name;
|
||||
}
|
||||
$default:
|
||||
// Fix this as we go along.
|
||||
extern fn NativeDirentry* readdir(void*);
|
||||
struct NativeDirentry
|
||||
{
|
||||
usz ino;
|
||||
isz seekoff;
|
||||
ushort reclen;
|
||||
char type;
|
||||
char[*] name;
|
||||
}
|
||||
$endswitch
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::io::file::os;
|
||||
module std::io::file::os @if(env::os_is_win32());
|
||||
import std::os::win32;
|
||||
|
||||
$if env::os_is_win32():
|
||||
|
||||
const Win32_DWORD FILE_ATTRIBUTE_READONLY = 0x01;
|
||||
const Win32_DWORD FILE_ATTRIBUTE_HIDDEN = 0x02;
|
||||
const Win32_DWORD FILE_ATTRIBUTE_SYSTEM = 0x04;
|
||||
@@ -110,4 +108,3 @@ fn Path! native_temp_directory(Allocator* using = mem::heap())
|
||||
}
|
||||
}
|
||||
*/
|
||||
$endif
|
||||
@@ -1,51 +1,42 @@
|
||||
module std::io::os;
|
||||
import libc;
|
||||
|
||||
$switch
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
|
||||
macro String! getcwd(Allocator* using = mem::heap())
|
||||
{
|
||||
const DEFAULT_BUFFER = 256;
|
||||
Char16[DEFAULT_BUFFER] buffer;
|
||||
Char16 *res = win32::_wgetcwd(&buffer, DEFAULT_BUFFER);
|
||||
bool free = false;
|
||||
defer if (free) libc::free(res);
|
||||
if (!res)
|
||||
{
|
||||
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
|
||||
res = win32::_wgetcwd(null, 0);
|
||||
free = true;
|
||||
}
|
||||
Char16[] str16 = res[:win32::wcslen(res)];
|
||||
return string::from_utf16(str16, using);
|
||||
$switch
|
||||
$case WIN32_LIBC:
|
||||
const DEFAULT_BUFFER = 256;
|
||||
Char16[DEFAULT_BUFFER] buffer;
|
||||
Char16 *res = win32::_wgetcwd(&buffer, DEFAULT_BUFFER);
|
||||
bool free = false;
|
||||
defer if (free) libc::free(res);
|
||||
if (!res)
|
||||
{
|
||||
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
|
||||
res = win32::_wgetcwd(null, 0);
|
||||
free = true;
|
||||
}
|
||||
Char16[] str16 = res[:win32::wcslen(res)];
|
||||
return string::from_utf16(str16, using);
|
||||
|
||||
$case POSIX_LIBC:
|
||||
const usz DEFAULT_BUFFER = 256;
|
||||
char[DEFAULT_BUFFER] buffer;
|
||||
ZString res = posix::getcwd(&buffer, DEFAULT_BUFFER);
|
||||
bool free = false;
|
||||
if (!res)
|
||||
{
|
||||
// Improve error
|
||||
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
|
||||
res = posix::getcwd(null, 0);
|
||||
free = true;
|
||||
}
|
||||
defer if (free) libc::free((void*)res);
|
||||
return res.copy(using);
|
||||
|
||||
$default:
|
||||
unreachable("'getcwd' not available");
|
||||
return "";
|
||||
$endswitch
|
||||
}
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
|
||||
|
||||
macro String! getcwd(Allocator* using = mem::heap())
|
||||
{
|
||||
const usz DEFAULT_BUFFER = 256;
|
||||
char[DEFAULT_BUFFER] buffer;
|
||||
ZString res = posix::getcwd(&buffer, DEFAULT_BUFFER);
|
||||
bool free = false;
|
||||
if (!res)
|
||||
{
|
||||
// Improve error
|
||||
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
|
||||
res = posix::getcwd(null, 0);
|
||||
free = true;
|
||||
}
|
||||
defer if (free) libc::free((void*)res);
|
||||
return res.copy(using);
|
||||
}
|
||||
|
||||
$default:
|
||||
|
||||
fn String! getcwd(Allocator* using = mem::heap())
|
||||
{
|
||||
unreachable("'getcwd' not available");
|
||||
}
|
||||
|
||||
$endswitch
|
||||
@@ -4,60 +4,48 @@ import std::io::path;
|
||||
import std::os::win32;
|
||||
import std::os::posix;
|
||||
|
||||
$switch
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
|
||||
|
||||
macro bool! native_mkdir(Path path, MkdirPermissions permissions)
|
||||
{
|
||||
if (!posix::mkdir(path.as_zstr(), permissions == NORMAL ? 0o777 : 0o700)) return true;
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EACCES:
|
||||
case errno::EPERM:
|
||||
case errno::EROFS:
|
||||
case errno::EFAULT: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::EDQUOT:
|
||||
case errno::ENOSPC: return IoError.OUT_OF_SPACE?;
|
||||
case errno::EISDIR:
|
||||
case errno::EEXIST: return false;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
case errno::ENOTDIR: return IoError.FILE_NOT_FOUND?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
}
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
|
||||
macro bool! native_mkdir(Path path, MkdirPermissions permissions)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
// TODO security attributes
|
||||
if (win32::win32_CreateDirectoryW(path.as_str().to_temp_utf16()!!, null)) return true;
|
||||
switch (win32::win32_GetLastError())
|
||||
{
|
||||
case win32::ERROR_ACCESS_DENIED:
|
||||
return IoError.NO_PERMISSION?;
|
||||
case win32::ERROR_DISK_FULL:
|
||||
return IoError.OUT_OF_SPACE?;
|
||||
case win32::ERROR_ALREADY_EXISTS:
|
||||
return false;
|
||||
case win32::ERROR_PATH_NOT_FOUND:
|
||||
return IoError.FILE_NOT_FOUND?;
|
||||
default:
|
||||
return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$default:
|
||||
|
||||
fn bool! native_mkdir(Path path, MkdirPermissions permissions)
|
||||
{
|
||||
unreachable("'mkdir' not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$endswitch
|
||||
$switch
|
||||
$case POSIX_LIBC:
|
||||
if (!posix::mkdir(path.as_zstr(), permissions == NORMAL ? 0o777 : 0o700)) return true;
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EACCES:
|
||||
case errno::EPERM:
|
||||
case errno::EROFS:
|
||||
case errno::EFAULT: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::EDQUOT:
|
||||
case errno::ENOSPC: return IoError.OUT_OF_SPACE?;
|
||||
case errno::EISDIR:
|
||||
case errno::EEXIST: return false;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
case errno::ENOTDIR: return IoError.FILE_NOT_FOUND?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
$case WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
// TODO security attributes
|
||||
if (win32::win32_CreateDirectoryW(path.as_str().to_temp_utf16()!!, null)) return true;
|
||||
switch (win32::win32_GetLastError())
|
||||
{
|
||||
case win32::ERROR_ACCESS_DENIED:
|
||||
return IoError.NO_PERMISSION?;
|
||||
case win32::ERROR_DISK_FULL:
|
||||
return IoError.OUT_OF_SPACE?;
|
||||
case win32::ERROR_ALREADY_EXISTS:
|
||||
return false;
|
||||
case win32::ERROR_PATH_NOT_FOUND:
|
||||
return IoError.FILE_NOT_FOUND?;
|
||||
default:
|
||||
return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
};
|
||||
$default:
|
||||
unreachable("'mkdir' not available");
|
||||
return false;
|
||||
$endswitch
|
||||
}
|
||||
@@ -4,58 +4,46 @@ import std::io::path;
|
||||
import std::os::win32;
|
||||
import std::os::posix;
|
||||
|
||||
$switch
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
|
||||
|
||||
macro bool! native_rmdir(Path path)
|
||||
{
|
||||
if (!posix::rmdir(path.as_zstr())) return true;
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EBUSY: return IoError.BUSY?;
|
||||
case errno::EACCES:
|
||||
case errno::EPERM:
|
||||
case errno::EROFS:
|
||||
case errno::EFAULT: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::ENOTDIR:
|
||||
case errno::ENOENT: return false;
|
||||
case errno::ENOTEMPTY: return IoError.DIR_NOT_EMPTY?;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
$switch
|
||||
$case POSIX_LIBC:
|
||||
if (!posix::rmdir(path.as_zstr())) return true;
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EBUSY: return IoError.BUSY?;
|
||||
case errno::EACCES:
|
||||
case errno::EPERM:
|
||||
case errno::EROFS:
|
||||
case errno::EFAULT: return IoError.NO_PERMISSION?;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
|
||||
case errno::ENOTDIR:
|
||||
case errno::ENOENT: return false;
|
||||
case errno::ENOTEMPTY: return IoError.DIR_NOT_EMPTY?;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
|
||||
default: return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
$case WIN32_LIBC:
|
||||
@pool()
|
||||
{
|
||||
if (win32::win32_RemoveDirectoryW(path.as_str().to_temp_utf16()!!)) return true;
|
||||
switch (win32::win32_GetLastError())
|
||||
{
|
||||
case win32::ERROR_ACCESS_DENIED:
|
||||
return IoError.NO_PERMISSION?;
|
||||
case win32::ERROR_CURRENT_DIRECTORY:
|
||||
return IoError.BUSY?;
|
||||
case win32::ERROR_DIR_NOT_EMPTY:
|
||||
return IoError.DIR_NOT_EMPTY?;
|
||||
case win32::ERROR_DIRECTORY:
|
||||
case win32::ERROR_PATH_NOT_FOUND:
|
||||
return false;
|
||||
default:
|
||||
return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
};
|
||||
$default:
|
||||
unreachable("'rmdir' not available");
|
||||
return false;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
|
||||
macro bool! native_rmdir(Path path)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
if (win32::win32_RemoveDirectoryW(path.as_str().to_temp_utf16()!!)) return true;
|
||||
switch (win32::win32_GetLastError())
|
||||
{
|
||||
case win32::ERROR_ACCESS_DENIED:
|
||||
return IoError.NO_PERMISSION?;
|
||||
case win32::ERROR_CURRENT_DIRECTORY:
|
||||
return IoError.BUSY?;
|
||||
case win32::ERROR_DIR_NOT_EMPTY:
|
||||
return IoError.DIR_NOT_EMPTY?;
|
||||
case win32::ERROR_DIRECTORY:
|
||||
case win32::ERROR_PATH_NOT_FOUND:
|
||||
return false;
|
||||
default:
|
||||
return IoError.GENERAL_ERROR?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$default:
|
||||
|
||||
fn bool! native_rmdir(Path path)
|
||||
{
|
||||
unreachable("'rmdir' not available");
|
||||
}
|
||||
|
||||
$endswitch
|
||||
@@ -96,11 +96,11 @@ fn bool! rmdir(Path path)
|
||||
fn void! rmtree(Path path)
|
||||
{
|
||||
if (!path.path_string.len) return PathResult.INVALID_PATH?;
|
||||
$if $defined(os::native_rmtree):
|
||||
return os::native_rmtree(path);
|
||||
$else
|
||||
assert(false, "rmtree is not available");
|
||||
$endif
|
||||
$if $defined(os::native_rmtree):
|
||||
return os::native_rmtree(path);
|
||||
$else
|
||||
assert(false, "rmtree is not available");
|
||||
$endif
|
||||
}
|
||||
|
||||
fn Path! new(String path, Allocator* using = mem::heap(), PathEnv path_env = DEFAULT_PATH_ENV)
|
||||
|
||||
@@ -35,7 +35,7 @@ def TerminateFunction = fn void();
|
||||
def CompareFunction = fn int(void*, void*);
|
||||
def JmpBuf = uptr[$$JMP_BUF_SIZE];
|
||||
|
||||
$if env::COMPILER_LIBC_AVAILABLE:
|
||||
module libc @if(env::COMPILER_LIBC_AVAILABLE);
|
||||
|
||||
extern fn double atof(char* str);
|
||||
extern fn int atoi(char* str);
|
||||
@@ -59,13 +59,12 @@ extern fn int rand();
|
||||
extern fn void srand(uint seed);
|
||||
|
||||
extern fn void longjmp(JmpBuf* buffer, CInt value);
|
||||
$if env::os_is_win32():
|
||||
|
||||
// TODO win32 aarch64
|
||||
extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer);
|
||||
macro CInt setjmp(JmpBuf* buffer) => _setjmp($$frameaddress(), buffer);
|
||||
$else
|
||||
extern fn CInt setjmp(JmpBuf* buffer);
|
||||
$endif
|
||||
extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer) @if(env::WIN32);
|
||||
macro CInt setjmp(JmpBuf* buffer) @if(env::WIN32) => _setjmp($$frameaddress(), buffer);
|
||||
|
||||
extern fn CInt setjmp(JmpBuf* buffer) @if(!env::WIN32);
|
||||
// MB functions omitted
|
||||
|
||||
// string
|
||||
@@ -97,7 +96,110 @@ extern fn void* calloc(usz count, usz size);
|
||||
extern fn void* free(void*);
|
||||
extern fn void* realloc(void* ptr, usz size);
|
||||
|
||||
$else
|
||||
extern fn int fclose(CFile stream);
|
||||
extern fn void clearerr(CFile stream);
|
||||
extern fn int feof(CFile stream);
|
||||
extern fn int ferror(CFile stream);
|
||||
extern fn int fflush(CFile stream);
|
||||
extern fn int fgetpos(CFile stream, Fpos* pos);
|
||||
extern fn CFile fopen(ZString filename, ZString mode);
|
||||
extern fn usz fread(void* ptr, usz size, usz nmemb, CFile stream);
|
||||
extern fn CFile freopen(ZString filename, ZString mode, CFile stream);
|
||||
extern fn CFile fmemopen(void* ptr, usz size, ZString mode);
|
||||
extern fn int fseek(CFile stream, SeekIndex offset, int whence);
|
||||
extern fn int fsetpos(CFile stream, Fpos* pos);
|
||||
extern fn SeekIndex ftell(CFile stream);
|
||||
extern fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream);
|
||||
extern fn int remove(char* filename);
|
||||
extern fn int rename(char* old_name, char* new_name);
|
||||
extern fn void rewind(CFile stream);
|
||||
extern fn void setbuf(CFile stream, char* buffer);
|
||||
extern fn void setvbuf(CFile stream, char* buffer, int mode, usz size);
|
||||
extern fn CFile tmpnam(char* str);
|
||||
extern fn int fprintf(CFile stream, char* format, ...);
|
||||
extern fn int printf(char* format, ...);
|
||||
extern fn int sprintf(char* str, char* format, ...);
|
||||
extern fn int snprintf(char* str, usz size, char* format, ...);
|
||||
extern fn int fscanf(CFile stream, char* format, ...);
|
||||
extern fn int scanf(char* format, ...);
|
||||
extern fn int sscanf(char* str, char* format, ...);
|
||||
extern fn int fgetc(CFile stream);
|
||||
extern fn char* fgets(char* str, int n, CFile stream);
|
||||
extern fn int fputc(int c, CFile stream);
|
||||
extern fn int getc(CFile stream);
|
||||
extern fn int getchar();
|
||||
extern fn int putc(int c, CFile stream);
|
||||
extern fn int putchar(int c);
|
||||
extern fn int puts(char* str);
|
||||
extern fn int ungetc(int c, CFile stream);
|
||||
extern fn void perror(char* str);
|
||||
extern fn isz getline(char** linep, usz* linecapp, CFile stream);
|
||||
|
||||
extern fn int timespec_get(TimeSpec* ts, int base);
|
||||
extern fn int nanosleep(TimeSpec* req, TimeSpec* remaining);
|
||||
|
||||
extern fn ZString asctime(Tm *timeptr);
|
||||
extern fn Clock_t clock();
|
||||
extern fn ZString ctime(Time_t *timer);
|
||||
extern fn double difftime(Time_t time1, Time_t time2);
|
||||
extern fn Tm* gmtime(Time_t *timer);
|
||||
extern fn Tm* localtime(Time_t *timer);
|
||||
extern fn usz strftime(char* str, usz maxsize, char* format, Tm *timeptr);
|
||||
extern fn Time_t time(Time_t *timer);
|
||||
|
||||
// signal
|
||||
def SignalFunction = fn void(int);
|
||||
extern fn SignalFunction signal(int sig, SignalFunction function);
|
||||
// Incomplete
|
||||
|
||||
module libc @if(LINUX_LIBC);
|
||||
extern CFile __stdin @extern("stdin");
|
||||
extern CFile __stdout @extern("stdout");
|
||||
extern CFile __stderr @extern("stderr");
|
||||
extern fn usz malloc_usable_size(void* ptr);
|
||||
macro usz malloc_size(void* ptr) => malloc_usable_size(ptr);
|
||||
extern fn void* aligned_alloc(usz align, usz size);
|
||||
macro CFile stdin() => __stdin;
|
||||
macro CFile stdout() => __stdout;
|
||||
macro CFile stderr() => __stderr;
|
||||
|
||||
module libc @if(DARWIN_LIBC);
|
||||
extern CFile __stdinp;
|
||||
extern CFile __stdoutp;
|
||||
extern CFile __stderrp;
|
||||
extern fn usz malloc_size(void* ptr);
|
||||
extern fn void* aligned_alloc(usz align, usz size);
|
||||
macro CFile stdin() => __stdinp;
|
||||
macro CFile stdout() => __stdoutp;
|
||||
macro CFile stderr() => __stderrp;
|
||||
|
||||
module libc @if(WIN32_LIBC);
|
||||
extern fn CFile __acrt_iob_func(CInt c);
|
||||
extern fn usz _msize(void* ptr);
|
||||
macro usz malloc_size(void* ptr) => _msize(ptr);
|
||||
macro CFile stdin() => __acrt_iob_func(0);
|
||||
macro CFile stdout() => __acrt_iob_func(1);
|
||||
macro CFile stderr() => __acrt_iob_func(2);
|
||||
extern fn Tm* _gmtime64_s(Tm* buf, Time_t *timer);
|
||||
extern fn Tm* _localtime64_s(Tm* buf, Time_t *timer);
|
||||
extern fn void _get_timezone(CLong *timezone);
|
||||
macro Tm* gmtime_r(Time_t *timer, Tm* buf) => _gmtime64_s(buf, timer);
|
||||
macro Tm* localtime_r(Time_t *timer, Tm* buf) => _localtime64_s(buf, timer);
|
||||
extern fn Time_t mktime(Tm *timeptr) @extern("_mktime64");
|
||||
extern fn Time_t timegm(Tm *timeptr) @extern("_mkgmtime64");
|
||||
|
||||
module libc @if(env::COMPILER_LIBC_AVAILABLE && !env::WIN32 && !env::LINUX && !env::DARWIN);
|
||||
macro CFile stdin() { return (CFile*)(uptr)0; }
|
||||
macro CFile stdout() { return (CFile*)(uptr)1; }
|
||||
macro CFile stderr() { return (CFile*)(uptr)2; }
|
||||
|
||||
module libc @if(env::COMPILER_LIBC_AVAILABLE && !env::WIN32);
|
||||
extern fn Tm* gmtime_r(Time_t *timer, Tm* buf);
|
||||
extern fn Tm* localtime_r(Time_t *timer, Tm* buf);
|
||||
extern fn Time_t mktime(Tm *timeptr);
|
||||
extern fn Time_t timegm(Tm *timeptr);
|
||||
|
||||
module libc @if(!env::COMPILER_LIBC_AVAILABLE);
|
||||
|
||||
fn void longjmp(JmpBuf* buffer, CInt value) @weak @extern("longjmp") @nostrip
|
||||
{
|
||||
@@ -144,110 +246,6 @@ fn void* memset(void* dest, CInt value, usz n) @weak @extern("memset") @nostrip
|
||||
return dest;
|
||||
}
|
||||
|
||||
$endif
|
||||
|
||||
// stdio
|
||||
|
||||
def Fpos = long;
|
||||
def CFile = void*;
|
||||
|
||||
$switch
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
|
||||
extern CFile __stdin @extern("stdin");
|
||||
extern CFile __stdout @extern("stdout");
|
||||
extern CFile __stderr @extern("stderr");
|
||||
extern fn usz malloc_usable_size(void* ptr);
|
||||
macro usz malloc_size(void* ptr) { return malloc_usable_size(ptr); }
|
||||
extern fn void* aligned_alloc(usz align, usz size);
|
||||
macro CFile stdin() { return __stdin; }
|
||||
macro CFile stdout() { return __stdout; }
|
||||
macro CFile stderr() { return __stderr; }
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_darwin():
|
||||
extern CFile __stdinp;
|
||||
extern CFile __stdoutp;
|
||||
extern CFile __stderrp;
|
||||
extern fn usz malloc_size(void* ptr);
|
||||
extern fn void* aligned_alloc(usz align, usz size);
|
||||
macro CFile stdin() { return __stdinp; }
|
||||
macro CFile stdout() { return __stdoutp; }
|
||||
macro CFile stderr() { return __stderrp; }
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
extern fn CFile __acrt_iob_func(CInt c);
|
||||
extern fn usz _msize(void* ptr);
|
||||
macro usz malloc_size(void* ptr) { return _msize(ptr); }
|
||||
macro CFile stdin() { return __acrt_iob_func(0); }
|
||||
macro CFile stdout() { return __acrt_iob_func(1); }
|
||||
macro CFile stderr() { return __acrt_iob_func(2); }
|
||||
$default:
|
||||
macro CFile stdin() { return (CFile*)(uptr)0; }
|
||||
macro CFile stdout() { return (CFile*)(uptr)1; }
|
||||
macro CFile stderr() { return (CFile*)(uptr)2; }
|
||||
$endswitch
|
||||
|
||||
const HAS_MALLOC_SIZE =
|
||||
env::OS_TYPE == LINUX
|
||||
|| env::os_is_win32()
|
||||
|| env::os_is_darwin();
|
||||
|
||||
// The following needs to be set per arch+os
|
||||
// For now I have simply pulled the defaults from MacOS
|
||||
const int SEEK_SET = 0;
|
||||
const int SEEK_CUR = 1;
|
||||
const int SEEK_END = 2;
|
||||
const int _IOFBF = 0; // Fully buffered
|
||||
const int _IOLBF = 1; // Line buffered
|
||||
const int _IONBF = 2; // Unbuffered
|
||||
const int BUFSIZ = 1024;
|
||||
const int EOF = -1;
|
||||
const int FOPEN_MAX = 20;
|
||||
const int FILENAME_MAX = 1024;
|
||||
|
||||
def Errno = distinct CInt;
|
||||
def SeekIndex = CLong;
|
||||
|
||||
$if env::COMPILER_LIBC_AVAILABLE:
|
||||
|
||||
extern fn int fclose(CFile stream);
|
||||
extern fn void clearerr(CFile stream);
|
||||
extern fn int feof(CFile stream);
|
||||
extern fn int ferror(CFile stream);
|
||||
extern fn int fflush(CFile stream);
|
||||
extern fn int fgetpos(CFile stream, Fpos* pos);
|
||||
extern fn CFile fopen(ZString filename, ZString mode);
|
||||
extern fn usz fread(void* ptr, usz size, usz nmemb, CFile stream);
|
||||
extern fn CFile freopen(ZString filename, ZString mode, CFile stream);
|
||||
extern fn CFile fmemopen(void* ptr, usz size, ZString mode);
|
||||
extern fn int fseek(CFile stream, SeekIndex offset, int whence);
|
||||
extern fn int fsetpos(CFile stream, Fpos* pos);
|
||||
extern fn SeekIndex ftell(CFile stream);
|
||||
extern fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream);
|
||||
extern fn int remove(char* filename);
|
||||
extern fn int rename(char* old_name, char* new_name);
|
||||
extern fn void rewind(CFile stream);
|
||||
extern fn void setbuf(CFile stream, char* buffer);
|
||||
extern fn void setvbuf(CFile stream, char* buffer, int mode, usz size);
|
||||
extern fn CFile tmpnam(char* str);
|
||||
extern fn int fprintf(CFile stream, char* format, ...);
|
||||
extern fn int printf(char* format, ...);
|
||||
extern fn int sprintf(char* str, char* format, ...);
|
||||
extern fn int snprintf(char* str, usz size, char* format, ...);
|
||||
extern fn int fscanf(CFile stream, char* format, ...);
|
||||
extern fn int scanf(char* format, ...);
|
||||
extern fn int sscanf(char* str, char* format, ...);
|
||||
extern fn int fgetc(CFile stream);
|
||||
extern fn char* fgets(char* str, int n, CFile stream);
|
||||
extern fn int fputc(int c, CFile stream);
|
||||
extern fn int getc(CFile stream);
|
||||
extern fn int getchar();
|
||||
extern fn int putc(int c, CFile stream);
|
||||
extern fn int putchar(int c);
|
||||
extern fn int puts(char* str);
|
||||
extern fn int ungetc(int c, CFile stream);
|
||||
extern fn void perror(char* str);
|
||||
extern fn isz getline(char** linep, usz* linecapp, CFile stream);
|
||||
|
||||
$else
|
||||
|
||||
fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extern("fseek") @nostrip
|
||||
{
|
||||
unreachable("'fseek' not available.");
|
||||
@@ -315,12 +313,40 @@ fn int puts(ZString str) @weak @extern("puts") @nostrip
|
||||
unreachable("'puts' not available.");
|
||||
}
|
||||
|
||||
$endif
|
||||
module libc;
|
||||
|
||||
// stdio
|
||||
|
||||
def Fpos = long;
|
||||
def CFile = void*;
|
||||
|
||||
|
||||
const HAS_MALLOC_SIZE =
|
||||
env::OS_TYPE == LINUX
|
||||
|| env::os_is_win32()
|
||||
|| env::os_is_darwin();
|
||||
|
||||
// The following needs to be set per arch+os
|
||||
// For now I have simply pulled the defaults from MacOS
|
||||
const int SEEK_SET = 0;
|
||||
const int SEEK_CUR = 1;
|
||||
const int SEEK_END = 2;
|
||||
const int _IOFBF = 0; // Fully buffered
|
||||
const int _IOLBF = 1; // Line buffered
|
||||
const int _IONBF = 2; // Unbuffered
|
||||
const int BUFSIZ = 1024;
|
||||
const int EOF = -1;
|
||||
const int FOPEN_MAX = 20;
|
||||
const int FILENAME_MAX = 1024;
|
||||
|
||||
def Errno = distinct CInt;
|
||||
def SeekIndex = CLong;
|
||||
|
||||
// vsprintf vprintf not supported
|
||||
|
||||
// time.h
|
||||
|
||||
struct TmCommon @private
|
||||
struct Tm
|
||||
{
|
||||
int tm_sec; /* seconds after the minute [0-60] */
|
||||
int tm_min; /* minutes after the hour [0-59] */
|
||||
@@ -331,112 +357,33 @@ struct TmCommon @private
|
||||
int tm_wday; /* days since Sunday [0-6] */
|
||||
int tm_yday; /* days since January 1 [0-365] */
|
||||
int tm_isdst; /* Daylight Savings Time flag */
|
||||
TimeOffset tm_gmtoff @if(!env::WIN32); /* offset from UTC in seconds */
|
||||
char *tm_zone @if(!env::WIN32); /* timezone abbreviation */
|
||||
int tm_nsec @if(env::WASI);
|
||||
|
||||
}
|
||||
|
||||
|
||||
$switch (env::OS_TYPE)
|
||||
|
||||
$case WIN32:
|
||||
|
||||
def Tm = TmCommon;
|
||||
|
||||
$case WASI:
|
||||
|
||||
def TimeOffset = int;
|
||||
struct Tm
|
||||
{
|
||||
inline TmCommon common;
|
||||
TimeOffset tm_gmtoff; /* offset from UTC in seconds */
|
||||
char *tm_zone; /* timezone abbreviation */
|
||||
int tm_nsec;
|
||||
}
|
||||
|
||||
$case MACOS:
|
||||
$case IOS:
|
||||
$case TVOS:
|
||||
$case WATCHOS:
|
||||
$case OPENBSD:
|
||||
$case FREEBSD:
|
||||
$default:
|
||||
|
||||
def TimeOffset = CLong;
|
||||
struct Tm
|
||||
{
|
||||
inline TmCommon common;
|
||||
TimeOffset tm_gmtoff; /* offset from UTC in seconds */
|
||||
char *tm_zone; /* timezone abbreviation */
|
||||
}
|
||||
|
||||
$endswitch
|
||||
|
||||
|
||||
$if env::os_is_win32():
|
||||
|
||||
struct TimeSpec
|
||||
{
|
||||
Time_t s;
|
||||
ulong ns;
|
||||
ulong ns @if(env::WIN32);
|
||||
CLong ns @if(!env::WIN32);
|
||||
}
|
||||
|
||||
def Time_t = long;
|
||||
def Clock_t = ulong;
|
||||
def Time_t = long @if(env::WIN32);
|
||||
def Time_t = CLong @if(!env::WIN32);
|
||||
def Clock_t = ulong @if(env::WIN32);
|
||||
def Clock_t = CULong @if(!env::WIN32);
|
||||
|
||||
$else
|
||||
|
||||
struct TimeSpec
|
||||
{
|
||||
Time_t s;
|
||||
CLong ns;
|
||||
}
|
||||
|
||||
def Time_t = CLong;
|
||||
def Clock_t = CULong;
|
||||
|
||||
$endif
|
||||
def TimeOffset = int @if(env::WASI) ;
|
||||
def TimeOffset = CLong @if(!env::WASI) ;
|
||||
|
||||
const int TIME_UTC = 1;
|
||||
|
||||
extern fn int timespec_get(TimeSpec* ts, int base);
|
||||
extern fn int nanosleep(TimeSpec* req, TimeSpec* remaining);
|
||||
|
||||
// Likely wrong, must be per platform.
|
||||
const CLOCKS_PER_SEC = 1000000;
|
||||
|
||||
|
||||
extern fn ZString asctime(Tm *timeptr);
|
||||
extern fn Clock_t clock();
|
||||
extern fn ZString ctime(Time_t *timer);
|
||||
extern fn double difftime(Time_t time1, Time_t time2);
|
||||
extern fn Tm* gmtime(Time_t *timer);
|
||||
|
||||
extern fn Tm* localtime(Time_t *timer);
|
||||
|
||||
$if env::os_is_win32():
|
||||
extern fn Tm* _gmtime64_s(Tm* buf, Time_t *timer);
|
||||
extern fn Tm* _localtime64_s(Tm* buf, Time_t *timer);
|
||||
extern fn void _get_timezone(CLong *timezone);
|
||||
|
||||
macro Tm* gmtime_r(Time_t *timer, Tm* buf) => _gmtime64_s(buf, timer);
|
||||
macro Tm* localtime_r(Time_t *timer, Tm* buf) => _localtime64_s(buf, timer);
|
||||
|
||||
extern fn Time_t mktime(Tm *timeptr) @extern("_mktime64");
|
||||
extern fn Time_t timegm(Tm *timeptr) @extern("_mkgmtime64");
|
||||
$else
|
||||
extern fn Tm* gmtime_r(Time_t *timer, Tm* buf);
|
||||
extern fn Tm* localtime_r(Time_t *timer, Tm* buf);
|
||||
extern fn Time_t mktime(Tm *timeptr);
|
||||
extern fn Time_t timegm(Tm *timeptr);
|
||||
$endif
|
||||
|
||||
extern fn usz strftime(char* str, usz maxsize, char* format, Tm *timeptr);
|
||||
extern fn Time_t time(Time_t *timer);
|
||||
|
||||
// signal
|
||||
def SignalFunction = fn void(int);
|
||||
extern fn SignalFunction signal(int sig, SignalFunction function);
|
||||
// Incomplete
|
||||
|
||||
|
||||
module libc::errno;
|
||||
|
||||
const Errno OK = 0;
|
||||
@@ -451,11 +398,9 @@ const Errno ENOEXEC = 8; // Exec format error
|
||||
const Errno EBADF = 9; // Bad file number
|
||||
const Errno ECHILD = 10; // No child processes
|
||||
|
||||
$if env::os_is_darwin():
|
||||
const Errno EAGAIN = 35; // Try again Macos
|
||||
$else
|
||||
const Errno EAGAIN = 11; // Try again
|
||||
$endif
|
||||
|
||||
const Errno EAGAIN @if(env::DARWIN) = 35; // Try again Macos
|
||||
const Errno EAGAIN @if(!env::DARWIN) = 11; // Try again
|
||||
|
||||
const Errno ENOMEM = 12; // Out of memory
|
||||
const Errno EACCES = 13; // Permission denied
|
||||
@@ -481,9 +426,7 @@ const Errno EPIPE = 32; // Broken pipe
|
||||
const Errno EDOM = 33; // Math argument out of domain of func
|
||||
const Errno ERANGE = 34; // Math result not representable
|
||||
|
||||
$switch (env::OS_TYPE)
|
||||
|
||||
$case MACOS:
|
||||
module libc::errno @if(env::DARWIN);
|
||||
const Errno EDEADLK = 11; // Resource deadlock would occur MacOS
|
||||
const Errno ENAMETOOLONG = 63; // File name too long MacOS
|
||||
const Errno ELOOP = 62; // Too many symbolic links encountered
|
||||
@@ -494,8 +437,13 @@ const Errno ENETUNREACH = 51; // Network is unreachable MacOS
|
||||
const Errno ENETRESET = 52; // Network dropped connection because of reset MacOS
|
||||
const Errno EOPNOTSUPP = 45; // Operation not supported on transport endpoint
|
||||
const Errno ENOTEMPTY = 66; // Directory not empty
|
||||
const Errno ETIMEDOUT = 60; // Connection timed out
|
||||
const Errno EINPROGRESS = 36; // Operation now in progress MacOS
|
||||
const Errno EALREADY = 37; // Operation already in progress MacOS
|
||||
const Errno EDQUOT = 69; // Quota exceeded, MacOS
|
||||
const Errno EWOULDBLOCK = 35; // Operation would block
|
||||
|
||||
$case WIN32:
|
||||
module libc::errno @if(env::WIN32);
|
||||
const Errno EDEADLK = 36; // Resource deadlock would occur Win32
|
||||
const Errno ENAMETOOLONG = 38; // File name too long Win32
|
||||
const Errno ELOOP = 114; // Too many symbolic links encountered
|
||||
@@ -506,8 +454,13 @@ const Errno ENETUNREACH = 118; // Network is unreachable
|
||||
const Errno ENETRESET = 117; // Network dropped connection because of reset
|
||||
const Errno EOPNOTSUPP = 130; // Operation not supported on transport endpoint
|
||||
const Errno ENOTEMPTY = 41; // Directory not empty
|
||||
const Errno ETIMEDOUT = 138; // Connection timed out
|
||||
const Errno EALREADY = 103; // Operation already in progress
|
||||
const Errno EINPROGRESS = 112; // Operation now in progress Win32
|
||||
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
|
||||
const Errno EWOULDBLOCK = 140; // Operation would block
|
||||
|
||||
$default:
|
||||
module libc::errno @if(!env::WIN32 && !env::DARWIN);
|
||||
const Errno EDEADLK = 35; // Resource deadlock would occur Linux (others?)
|
||||
const Errno ENAMETOOLONG = 36; // File name too long Linux (others?)
|
||||
const Errno ELOOP = 40; // Too many symbolic links encountered
|
||||
@@ -518,9 +471,11 @@ const Errno ENETUNREACH = 101; // Network is unreachable
|
||||
const Errno ENETRESET = 102; // Network dropped connection because of reset
|
||||
const Errno EOPNOTSUPP = 95; // Operation not supported on transport endpoint
|
||||
const Errno ENOTEMPTY = 39; // Directory not empty
|
||||
|
||||
$endswitch
|
||||
|
||||
const Errno ETIMEDOUT = 110; // Connection timed out
|
||||
const Errno EALREADY = 114; // Operation already in progress
|
||||
const Errno EINPROGRESS = 115; // Operation now in progress
|
||||
const Errno EDQUOT = 122; // Quota exceeded
|
||||
const Errno EWOULDBLOCK = 41; // Operation would block
|
||||
|
||||
|
||||
/*
|
||||
@@ -594,29 +549,6 @@ const Errno EHOSTDOWN = 112; /* Host is down */
|
||||
const Errno EHOSTUNREACH = 113; /* No route to host */
|
||||
*/
|
||||
|
||||
$switch (env::OS_TYPE)
|
||||
|
||||
$case MACOS:
|
||||
const Errno ETIMEDOUT = 60; // Connection timed out
|
||||
const Errno EINPROGRESS = 36; // Operation now in progress MacOS
|
||||
const Errno EALREADY = 37; // Operation already in progress MacOS
|
||||
const Errno EDQUOT = 69; // Quota exceeded, MacOS
|
||||
const Errno EWOULDBLOCK = 35; // Operation would block
|
||||
|
||||
$case WIN32:
|
||||
const Errno ETIMEDOUT = 138; // Connection timed out
|
||||
const Errno EALREADY = 103; // Operation already in progress
|
||||
const Errno EINPROGRESS = 112; // Operation now in progress Win32
|
||||
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
|
||||
const Errno EWOULDBLOCK = 140; // Operation would block
|
||||
|
||||
$default:
|
||||
const Errno ETIMEDOUT = 110; // Connection timed out
|
||||
const Errno EALREADY = 114; // Operation already in progress
|
||||
const Errno EINPROGRESS = 115; // Operation now in progress
|
||||
const Errno EDQUOT = 122; // Quota exceeded
|
||||
const Errno EWOULDBLOCK = 41; // Operation would block
|
||||
$endswitch
|
||||
|
||||
/*
|
||||
const Errno ESTALE = 116; /* Stale NFS file handle */
|
||||
|
||||
@@ -1,38 +1,28 @@
|
||||
module libc::os;
|
||||
|
||||
// Linux
|
||||
extern fn int* __errno_location() @if(LINUX_LIBC);
|
||||
macro int errno() @if(LINUX_LIBC) => *__errno_location();
|
||||
macro void errno_set(int err) @if(LINUX_LIBC) => *(__errno_location()) = err;
|
||||
|
||||
$switch
|
||||
// Darwin
|
||||
extern fn int* __error() @if(DARWIN_LIBC);
|
||||
macro int errno() @if(DARWIN_LIBC) => *__error();
|
||||
macro void errno_set(int err) @if(DARWIN_LIBC) => *(__error()) = err;
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
|
||||
|
||||
extern fn int* __errno_location();
|
||||
macro int errno() => *__errno_location();
|
||||
macro void errno_set(int err) => *(__errno_location()) = err;
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == MACOS:
|
||||
|
||||
extern fn int* __error();
|
||||
macro int errno() => *__error();
|
||||
macro void errno_set(int err) => *(__error()) = err;
|
||||
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == WIN32:
|
||||
|
||||
macro int errno()
|
||||
// Win32
|
||||
macro int errno() @if(WIN32_LIBC)
|
||||
{
|
||||
int holder;
|
||||
_get_errno(&holder);
|
||||
return holder;
|
||||
}
|
||||
macro void errno_set(int err) @if(WIN32_LIBC) => _set_errno(err);
|
||||
extern fn void _get_errno(int* result) @if(WIN32_LIBC);
|
||||
extern fn void _set_errno(int err) @if(WIN32_LIBC);
|
||||
|
||||
macro void errno_set(int err) => _set_errno(err);
|
||||
|
||||
extern fn void _get_errno(int* result);
|
||||
extern fn void _set_errno(int err);
|
||||
|
||||
$default:
|
||||
|
||||
tlocal int _errno_c3 = 0;
|
||||
fn void errno_set(int err) => _errno_c3 = err;
|
||||
fn int errno() => _errno_c3;
|
||||
|
||||
$endswitch
|
||||
// Default
|
||||
const ERRNO_DEFAULT @local = !LINUX_LIBC && !DARWIN_LIBC && !WIN32_LIBC;
|
||||
tlocal int _errno_c3 @if(ERRNO_DEFAULT) = 0;
|
||||
fn void errno_set(int err) @if(ERRNO_DEFAULT) => _errno_c3 = err;
|
||||
fn int errno() @if(ERRNO_DEFAULT) => _errno_c3;
|
||||
@@ -471,14 +471,14 @@ macro sqrt(x) => $$sqrt(values::promote_int(x));
|
||||
macro tan(x)
|
||||
{
|
||||
var $Type = $typeof(x);
|
||||
$switch
|
||||
$case types::is_vector($Type):
|
||||
return $$sin(x) / $$cos(x);
|
||||
$case $Type.typeid == float.typeid:
|
||||
return _tanf(x);
|
||||
$default:
|
||||
return _tan(x);
|
||||
$endswitch
|
||||
$switch
|
||||
$case types::is_vector($Type):
|
||||
return $$sin(x) / $$cos(x);
|
||||
$case $Type.typeid == float.typeid:
|
||||
return _tanf(x);
|
||||
$default:
|
||||
return _tan(x);
|
||||
$endswitch
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -487,11 +487,11 @@ $endswitch
|
||||
macro bool is_finite(x)
|
||||
{
|
||||
$switch ($typeof(x))
|
||||
$case float:
|
||||
$case float16:
|
||||
return bitcast((float)x, uint) & 0x7fffffff < 0x7f800000;
|
||||
$default:
|
||||
return bitcast((double)x, ulong) & (~0u64 >> 1) < 0x7ffu64 << 52;
|
||||
$case float:
|
||||
$case float16:
|
||||
return bitcast((float)x, uint) & 0x7fffffff < 0x7f800000;
|
||||
$default:
|
||||
return bitcast((double)x, ulong) & (~0u64 >> 1) < 0x7ffu64 << 52;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */
|
||||
/*
|
||||
@@ -31,4 +29,3 @@ fn double __cos(double x, double y) @extern("__cos") @weak @nostrip
|
||||
return w + (((1.0 - w) - hz) + (z * r - x * y));
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_cosf.c */
|
||||
/*
|
||||
@@ -32,5 +30,3 @@ fn float __cosdf(double x) @extern("__cosdf") @weak @nostrip
|
||||
double r = C2 + z * C3;
|
||||
return (float)(((1.0f + z * C0) + w * C1) + (w * z) * r);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */
|
||||
/*
|
||||
@@ -31,5 +29,3 @@ fn double __sin(double x, double y, int iy) @extern("__sin") @weak @nostrip
|
||||
? x + v * (S1 + z * r)
|
||||
: x - ((z * (0.5 * y - v * r) - y) - v * S1);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_sinf.c */
|
||||
/*
|
||||
@@ -31,4 +29,3 @@ fn float __sindf(double x) @extern("__sindf") @weak @nostrip
|
||||
return (float)((x + s * (S1F + z * S2F)) + s * w * r);
|
||||
}
|
||||
|
||||
$endif
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */
|
||||
/*
|
||||
@@ -79,5 +77,3 @@ fn double __tan(double x, double y, int odd) @extern("__tan") @weak @nostrip
|
||||
double a0 = bitcast(d, double);
|
||||
return a0 + a * (1.0 + a0 * w0 + a0 * v);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_tanf.c */
|
||||
/*
|
||||
@@ -52,5 +50,3 @@ fn float __tandf(double x, int odd) @extern("__tandf") @weak @nostrip
|
||||
r = (x + s * u) + (s * w) * (t + w * r);
|
||||
return (float)(odd ? -1.0 / r : r);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc::atan;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
const double[*] ATANHI @private = {
|
||||
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
|
||||
@@ -320,5 +318,3 @@ fn float _atan2f(float y, float x) @weak @extern("atan2f") @nostrip
|
||||
default: return (z - PI_LO_F) - PI_F; /* atan(-,-) */
|
||||
}
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double _ceil(double x) @weak @extern("ceil") @nostrip
|
||||
{
|
||||
@@ -42,4 +40,3 @@ fn float _ceilf(float x) @weak @extern("ceilf") @nostrip
|
||||
return bitcast(u, float);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn float _cosf(float x) @extern("cosf") @weak @nostrip
|
||||
{
|
||||
@@ -54,7 +52,7 @@ fn float _cosf(float x) @extern("cosf") @weak @nostrip
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double _cos(double x) @extern("cos") @weak @nostrip
|
||||
fn double _cos(double x) @weak @nostrip
|
||||
{
|
||||
// High word of x.
|
||||
uint ix = (uint)(bitcast(x, ulong) >> 32);
|
||||
@@ -87,5 +85,3 @@ fn double _cos(double x) @extern("cos") @weak @nostrip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
macro uint _top12f(float x) @private => bitcast(x, uint) >> 20;
|
||||
|
||||
@@ -141,4 +139,3 @@ fn double _exp2(double x) @extern("exp2") @weak @nostrip
|
||||
is no spurious underflow here even without fma. */
|
||||
return scale + scale * tmp;
|
||||
}
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double _floor(double x) @weak @extern("floor") @nostrip
|
||||
{
|
||||
@@ -42,4 +40,3 @@ fn float _floorf(float x) @weak @extern("floorf") @nostrip
|
||||
return bitcast(u, float);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn float powf_broken(float x, float f) @extern("powf") @weak @nostrip
|
||||
{
|
||||
@@ -11,5 +9,3 @@ fn double pow_broken(double x, double y) @extern("pow") @weak @nostrip
|
||||
{
|
||||
unreachable("'pow' not supported");
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::math::nolibc;
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
import std::math;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
@@ -537,4 +535,3 @@ fn int __rem_pio2(double x, double *y)
|
||||
|
||||
|
||||
}
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double _round(double x) @extern("round") @weak @nostrip
|
||||
{
|
||||
@@ -53,4 +51,3 @@ fn float _roundf(float x) @extern("roundf") @weak @nostrip
|
||||
return y;
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double _scalbn(double x, int n) @weak @extern("scalbn") @nostrip
|
||||
{
|
||||
@@ -27,5 +25,3 @@ fn double _scalbn(double x, int n) @weak @extern("scalbn") @nostrip
|
||||
}
|
||||
return x * bitcast(((ulong)(0x3ff + n)) << 52, double);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
|
||||
/*
|
||||
@@ -119,4 +117,3 @@ fn double sin(double x) @extern("sin") @weak @nostrip
|
||||
}
|
||||
}
|
||||
}
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
|
||||
/*
|
||||
@@ -156,4 +154,3 @@ fn void sincos(double x, double *sin, double *cos) @extern("sincos") @weak @nost
|
||||
}
|
||||
}
|
||||
}
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */
|
||||
/*
|
||||
@@ -100,4 +98,3 @@ fn float tanf(float x) @extern("tanf") @weak @nostrip
|
||||
}
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc::trig;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double sincos_broken(double x) @extern("sincos") @weak @nostrip
|
||||
{
|
||||
@@ -8,4 +6,3 @@ fn double sincos_broken(double x) @extern("sincos") @weak @nostrip
|
||||
}
|
||||
|
||||
|
||||
$endif
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if !env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn double _trunc(double x) @weak @extern("trunc") @nostrip
|
||||
{
|
||||
@@ -28,4 +26,3 @@ fn float _truncf(float x) @weak @extern("truncf") @nostrip
|
||||
return bitcast(i, float);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -1,21 +1,32 @@
|
||||
module std::net::os;
|
||||
|
||||
$if $defined(PLATFORM_AF_INET):
|
||||
struct AddrInfo
|
||||
{
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
usz ai_addrlen;
|
||||
void* ai_addr;
|
||||
char* ai_canonname;
|
||||
AddrInfo* ai_next;
|
||||
}
|
||||
|
||||
$if !$defined(PLATFORM_O_NONBLOCK):
|
||||
const PLATFORM_O_NONBLOCK = 0;
|
||||
$endif
|
||||
const bool SUPPORTS_INET = env::WIN32 || env::DARWIN || env::LINUX;
|
||||
|
||||
const PLATFORM_O_NONBLOCK @if(!$defined(PLATFORM_O_NONBLOCK)) = 0;
|
||||
|
||||
const AI_PASSIVE = 0x1;
|
||||
const AI_CANONNAME = 0x2;
|
||||
const AI_NUMERICHOST = 0x4;
|
||||
|
||||
const int AF_UNSPEC = 0;
|
||||
const int AF_INET = PLATFORM_AF_INET;
|
||||
const int AF_APPLETALK = PLATFORM_AF_APPLETALK;
|
||||
const int AF_IPX = PLATFORM_AF_IPX;
|
||||
const int AF_INET6 = PLATFORM_AF_INET6;
|
||||
const int AF_INET @if(SUPPORTS_INET) = PLATFORM_AF_INET;
|
||||
const int AF_APPLETALK @if(SUPPORTS_INET) = PLATFORM_AF_APPLETALK;
|
||||
const int AF_IPX @if(SUPPORTS_INET) = PLATFORM_AF_IPX;
|
||||
const int AF_INET6 @if(SUPPORTS_INET) = PLATFORM_AF_INET6;
|
||||
|
||||
const O_NONBLOCK = PLATFORM_O_NONBLOCK;
|
||||
|
||||
$endif
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::net::os;
|
||||
module std::net::os @if(env::DARWIN);
|
||||
import libc;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
|
||||
const AI_NUMERICSERV = 0x1000;
|
||||
const AI_ALL = 0x100;
|
||||
const AI_V4MAPPED_CFG = 0x200;
|
||||
@@ -11,18 +9,6 @@ const AI_V4MAPPED = 0x800;
|
||||
const AI_UNUSABLE = 0x10000000;
|
||||
const AI_DEFAULT = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
|
||||
|
||||
struct AddrInfo
|
||||
{
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
usz ai_addrlen;
|
||||
void* ai_addr;
|
||||
char* ai_canonname;
|
||||
AddrInfo* ai_next;
|
||||
}
|
||||
|
||||
const int PLATFORM_AF_UNIX = 1;
|
||||
const int PLATFORM_AF_INET = 2;
|
||||
const int PLATFORM_AF_IMPLINK = 3;
|
||||
@@ -61,7 +47,4 @@ const int PLATFORM_AF_IEEE80211 = 37;
|
||||
const int PLATFORM_AF_UTUN = 38;
|
||||
const int PLATFORM_AF_VSOCK = 40;
|
||||
const int PLATFORM_AF_MAX = 41;
|
||||
|
||||
const int PLATFORM_O_NONBLOCK = 0x30;
|
||||
|
||||
$endif
|
||||
const int PLATFORM_O_NONBLOCK = 0x30;
|
||||
@@ -1,20 +1,6 @@
|
||||
module std::net::os;
|
||||
module std::net::os @if(env::LINUX);
|
||||
import libc;
|
||||
|
||||
$if env::OS_TYPE == LINUX:
|
||||
|
||||
struct AddrInfo
|
||||
{
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
usz ai_addrlen;
|
||||
void* ai_addr;
|
||||
char* ai_canonname;
|
||||
AddrInfo* ai_next;
|
||||
}
|
||||
|
||||
const int PLATFORM_AF_UNIX = 1;
|
||||
const int PLATFORM_AF_INET = 2;
|
||||
const int PLATFORM_AF_AX25 = 3;
|
||||
@@ -26,6 +12,4 @@ const int PLATFORM_AF_AAL5 = 8;
|
||||
const int PLATFORM_AF_X25 = 9;
|
||||
const int PLATFORM_AF_INET6 = 10;
|
||||
|
||||
const PLATFORM_O_NONBLOCK = 0o4000;
|
||||
|
||||
$endif
|
||||
const PLATFORM_O_NONBLOCK = 0o4000;
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::net::os;
|
||||
module std::net::os @if(env::POSIX && SUPPORTS_INET);
|
||||
import libc;
|
||||
|
||||
$if !env::os_is_win32() && $defined(AddrInfo):
|
||||
|
||||
const int F_GETFL = 3;
|
||||
const int F_SETFL = 4;
|
||||
|
||||
@@ -37,6 +35,4 @@ macro void! NativeSocket.set_non_blocking(NativeSocket this)
|
||||
macro bool NativeSocket.is_non_blocking(NativeSocket this)
|
||||
{
|
||||
return fcntl(this, F_GETFL, 0) & O_NONBLOCK == O_NONBLOCK;
|
||||
}
|
||||
|
||||
$endif
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::net::os;
|
||||
|
||||
$if env::os_is_win32():
|
||||
module std::net::os @if(env::WIN32);
|
||||
|
||||
const int PLATFORM_AF_INET = 1;
|
||||
const int PLATFORM_AF_IPX = 6;
|
||||
@@ -10,18 +8,6 @@ const int PLATFORM_AF_INET6 = 23;
|
||||
const int PLATFORM_AF_IRDA = 26;
|
||||
const int PLATFORM_AF_BTH = 32;
|
||||
|
||||
struct AddrInfo
|
||||
{
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
usz ai_addrlen;
|
||||
char* ai_canonname;
|
||||
void* ai_addr;
|
||||
AddrInfo* ai_next;
|
||||
}
|
||||
|
||||
def NativeSocket = distinct uptr;
|
||||
|
||||
extern fn int wsa_startup(int, void*) @extern("WSAStartup");
|
||||
@@ -29,5 +15,3 @@ extern fn int ioctlsocket(NativeSocket, long cmd, ulong *argp);
|
||||
extern fn int closesocket(NativeSocket);
|
||||
|
||||
macro NativeSocket.close(NativeSocket this) => closesocket(this);
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
module std::os::macos::cf @if(DARWIN_LIBC);
|
||||
|
||||
def CFAllocatorRef = distinct void*;
|
||||
def CFAllocatorContextRef = distinct void*;
|
||||
@@ -18,4 +16,3 @@ extern fn CFAllocatorRef _macos_CFAllocatorGetDefault() @extern("CFAllocatorGetD
|
||||
extern fn void _macos_CFAllocatorSetDefault(CFAllocatorRef allocator) @extern("CFAllocatorSetDefault");
|
||||
extern fn void* _macos_CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorAllocate");
|
||||
extern fn CFIndex _macos_CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorGetPreferredSizeForSize");
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
module std::os::macos::cf @if(DARWIN_LIBC);
|
||||
|
||||
def CFArrayRef = distinct void*;
|
||||
def CFArrayCallBacksRef = distinct void*;
|
||||
@@ -11,4 +9,3 @@ extern fn CFIndex _macos_CFArrayGetCount(CFArrayRef array) @extern("CFArrayGetCo
|
||||
extern fn void _macos_CFArrayAppendArray(CFMutableArrayRef theArray, CFArrayRef otherArray, CFRange otherRange) @extern("CFArrayAppendArray");
|
||||
extern fn CFMutableArrayRef _macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @extern("CFArrayCreateMutable");
|
||||
extern fn void _macos_CFArrayAppendValue(CFMutableArrayRef theArray, void *value) @extern("CFArrayAppendValue");
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
module std::os::macos::cf @if(DARWIN_LIBC);
|
||||
|
||||
def CFTypeRef = distinct void*;
|
||||
def CFIndex = isz;
|
||||
@@ -12,5 +10,3 @@ struct CFRange
|
||||
|
||||
extern fn CFTypeRef _macos_CFRetain(CFTypeRef cf) @extern("CFRetain");
|
||||
extern fn void _macos_CFRelease(CFTypeRef cf) @extern("CFRelease");
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::macos::objc;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
module std::os::macos::objc @if(DARWIN_LIBC);
|
||||
|
||||
def Class = distinct void*;
|
||||
def Method = distinct void*;
|
||||
@@ -45,5 +43,5 @@ extern fn Method _macos_class_getClassMethod(Class cls, Selector name) @extern("
|
||||
extern fn bool _macos_class_respondsToSelector(Class cls, Selector name) @extern("class_respondsToSelector");
|
||||
extern fn Selector _macos_sel_registerName(char* str) @extern("sel_registerName");
|
||||
extern fn Class _macos_objc_lookUpClass(char* name) @extern("objc_lookUpClass");
|
||||
$endif
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
module std::os::posix;
|
||||
|
||||
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
|
||||
module std::os::posix @if(POSIX_LIBC);
|
||||
|
||||
extern fn int rmdir(ZString);
|
||||
extern fn int mkdir(ZString, ushort mode_t);
|
||||
extern fn int chdir(ZString);
|
||||
extern fn ZString getcwd(char* pwd, usz len);
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::win32;
|
||||
|
||||
$if env::os_is_win32():
|
||||
module std::os::win32 @if(WIN32_LIBC);
|
||||
|
||||
enum Win32_GET_FILEEX_INFO_LEVELS
|
||||
{
|
||||
@@ -63,4 +61,3 @@ extern bool _win32_CreateSymbolicLinkW(Char16* symlink_file, Char16* target_file
|
||||
extern bool _win32_CopyFileW(Char16* from_file, Char16* to_file, bool no_overwrite) @extern("CopyFileW");
|
||||
extern ulong _win32_GetFullPathNameW(Char16* file_name, ulong buffer_len, Char16* buffer, Char16** file_part) @extern("GetFullPathNameW");
|
||||
*/
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::win32;
|
||||
|
||||
$if env::os_is_win32():
|
||||
module std::os::win32 @if(WIN32_LIBC);
|
||||
|
||||
extern fn Win32_DWORD win32_GetLastError() @extern("GetLastError");
|
||||
|
||||
@@ -224,4 +222,3 @@ const Win32_DWORD ERROR_MR_MID_NOT_FOUND = 0x13D;
|
||||
const Win32_DWORD ERROR_SCOPE_NOT_FOUND = 0x13E;
|
||||
const Win32_DWORD ERROR_UNDEFINED_SCOPE = 0x13F;
|
||||
|
||||
$endif
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::win32;
|
||||
|
||||
$if env::os_is_win32():
|
||||
module std::os::win32 @if(WIN32_LIBC);
|
||||
|
||||
extern fn bool win32_CreateProcessW(
|
||||
Win32_LPCWSTR lpApplicationName,
|
||||
@@ -14,5 +12,3 @@ extern fn bool win32_CreateProcessW(
|
||||
Win32_LPSTARTUPINFOW lpStartupInfo,
|
||||
Win32_LPPROCESS_INFORMATION lpProcessInformation
|
||||
) @extern("CreateProcessW");
|
||||
|
||||
$endif
|
||||
@@ -1,16 +1,12 @@
|
||||
module std::os::win32;
|
||||
module std::os::win32 @if(WIN32_LIBC);
|
||||
|
||||
def WSAError = distinct int;
|
||||
|
||||
$if env::os_is_win32():
|
||||
|
||||
extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError");
|
||||
extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError");
|
||||
$endif
|
||||
|
||||
module std::os::win32::wsa;
|
||||
module std::os::win32::wsa @if(env::WIN32);
|
||||
|
||||
$if env::os_is_win32():
|
||||
const WSAError INVALID_HANDLE = 6;
|
||||
const WSAError NOT_ENOUGHT_MEMORY = 8;
|
||||
const WSAError INVALID_PARAMETER = 87;
|
||||
@@ -32,5 +28,4 @@ const WSAError EMSGSIZE = 10040;
|
||||
const WSAError EPROTOTYPE = 10041;
|
||||
const WSAError ENOPROTOOPT = 10042;
|
||||
const WSAError EPROTONOSUPPORT = 10043;
|
||||
const WSAError ESOCKTNOSUPPORT = 10044;
|
||||
$endif
|
||||
const WSAError ESOCKTNOSUPPORT = 10044;
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::thread::os;
|
||||
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX);
|
||||
import libc;
|
||||
|
||||
$if thread::THREAD_MODEL == ThreadModel.POSIX:
|
||||
|
||||
const PTHREAD_MUTEX_NORMAL = 0;
|
||||
const PTHREAD_MUTEX_ERRORCHECK = 1;
|
||||
const PTHREAD_MUTEX_RECURSIVE = 2;
|
||||
@@ -13,23 +11,6 @@ def NativeThread = Pthread;
|
||||
def NativeOnceFlag = PthreadOnce;
|
||||
|
||||
def Pthread = distinct void*;
|
||||
|
||||
$if env::OS_TYPE == LINUX:
|
||||
def PthreadMutex = distinct ulong[5];
|
||||
def PthreadAttribute = distinct ulong[7];
|
||||
def PthreadMutexAttribute = distinct uint;
|
||||
def PthreadCondAttribute = distinct uint;
|
||||
def PthreadCond = distinct ulong[6];
|
||||
def PthreadOnce = distinct uint;
|
||||
$else
|
||||
def PthreadMutex = distinct ulong[8];
|
||||
def PthreadMutexAttribute = distinct ulong[2];
|
||||
def PthreadAttribute = distinct ulong[8];
|
||||
def PthreadCond = distinct ulong[6];
|
||||
def PthreadCondAttribute = distinct ulong[8];
|
||||
def PthreadOnce = distinct ulong[2];
|
||||
$endif
|
||||
|
||||
def PosixThreadFn = fn void*(void*);
|
||||
|
||||
extern fn int pthread_attr_destroy(PthreadAttribute*);
|
||||
@@ -236,4 +217,18 @@ fn void! native_sleep(double s)
|
||||
if (libc::nanosleep(&to, null)) return ThreadFault.INTERRUPTED?;
|
||||
}
|
||||
|
||||
$endif
|
||||
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX && !env::LINUX);
|
||||
def PthreadMutex = distinct ulong[8];
|
||||
def PthreadMutexAttribute = distinct ulong[2];
|
||||
def PthreadAttribute = distinct ulong[8];
|
||||
def PthreadCond = distinct ulong[6];
|
||||
def PthreadCondAttribute = distinct ulong[8];
|
||||
def PthreadOnce = distinct ulong[2];
|
||||
|
||||
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX && env::LINUX);
|
||||
def PthreadMutex = distinct ulong[5];
|
||||
def PthreadAttribute = distinct ulong[7];
|
||||
def PthreadMutexAttribute = distinct uint;
|
||||
def PthreadCondAttribute = distinct uint;
|
||||
def PthreadCond = distinct ulong[6];
|
||||
def PthreadOnce = distinct uint;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::thread::os;
|
||||
|
||||
$if thread::THREAD_MODEL == ThreadModel.WIN32:
|
||||
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.WIN32);
|
||||
|
||||
def NativeThread = Win32_HANDLE;
|
||||
|
||||
@@ -345,5 +343,3 @@ fn void! native_sleep_nano(ulong ns)
|
||||
{
|
||||
return native_sleep_ms(ns < 1000_000 ? 1 : ns / 1000_000);
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -2,11 +2,11 @@ module std::time::clock;
|
||||
|
||||
fn Clock now()
|
||||
{
|
||||
$if $defined(native_clock):
|
||||
return os::native_clock();
|
||||
$else
|
||||
return 0;
|
||||
$endif
|
||||
$if $defined(native_clock):
|
||||
return os::native_clock();
|
||||
$else
|
||||
return 0;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn NanoDuration Clock.mark(Clock* this)
|
||||
|
||||
@@ -36,14 +36,14 @@ fn TzDateTime DateTime.to_local(DateTime* this)
|
||||
dt.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1;
|
||||
dt.year_day = (ushort)tm.tm_yday;
|
||||
dt.time = this.time;
|
||||
$if $defined(tm.tm_gmtoff):
|
||||
dt.gmt_offset = (int)tm.tm_gmtoff;
|
||||
$else
|
||||
$assert $defined(libc::_get_timezone);
|
||||
CLong timezone;
|
||||
libc::_get_timezone(&timezone);
|
||||
dt.gmt_offset = (int)-timezone;
|
||||
$endif
|
||||
$if $defined(tm.tm_gmtoff):
|
||||
dt.gmt_offset = (int)tm.tm_gmtoff;
|
||||
$else
|
||||
$assert $defined(libc::_get_timezone);
|
||||
CLong timezone;
|
||||
libc::_get_timezone(&timezone);
|
||||
dt.gmt_offset = (int)-timezone;
|
||||
$endif
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::time::os;
|
||||
|
||||
$if env::os_is_darwin():
|
||||
module std::time::os @if(DARWIN_LIBC);
|
||||
|
||||
struct Darwin_mach_timebase_info
|
||||
{
|
||||
@@ -23,6 +21,3 @@ fn Clock native_clock()
|
||||
}
|
||||
return (Clock)(mach_absolute_time() * timebase.numer / timebase.denom);
|
||||
}
|
||||
|
||||
|
||||
$endif
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
module std::time::os;
|
||||
module std::time::os @if(POSIX_LIBC);
|
||||
import libc;
|
||||
|
||||
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
|
||||
extern fn void clock_gettime(int type, TimeSpec *time);
|
||||
|
||||
$switch (env::OS_TYPE)
|
||||
$case OPENBSD:
|
||||
fn Time native_timestamp()
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64);
|
||||
}
|
||||
|
||||
fn Clock native_clock() @if(!DARWIN_LIBC)
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns);
|
||||
}
|
||||
|
||||
module std::time::os @if(OPENBSD_LIBC);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 4;
|
||||
const CLOCK_UPTIME = 5;
|
||||
const CLOCK_BOOTTIME = 6;
|
||||
$case FREEBSD:
|
||||
|
||||
module std::time::os @if(FREEBSD_LIBC);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
@@ -29,21 +43,21 @@ const CLOCK_PROCESS_CPUTIME_ID = 15;
|
||||
const CLOCK_BOOTTIME = CLOCK_UPTIME;
|
||||
const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST;
|
||||
const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST;
|
||||
$case NETBSD:
|
||||
|
||||
module std::time::os @if(NETBSD_LIBC);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_VIRTUAL = 1;
|
||||
const CLOCK_PROF = 2;
|
||||
const CLOCK_MONOTONIC = 3;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
|
||||
$case WASI:
|
||||
|
||||
module std::time::os @if(WASI_LIBC);
|
||||
// Not implemented
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 0;
|
||||
$case MACOS:
|
||||
$case TVOS:
|
||||
$case IOS:
|
||||
$case WATCHOS:
|
||||
|
||||
module std::time::os @if(DARWIN_LIBC);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 6;
|
||||
const CLOCK_MONOTONIC_RAW = 4;
|
||||
@@ -52,8 +66,8 @@ const CLOCK_UPTIME_RAW = 8;
|
||||
const CLOCK_UPTIME_RAW_APPROX = 9;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 12;
|
||||
const CLOCK_THREAD_CPUTIME_ID = 16;
|
||||
$case LINUX:
|
||||
$default:
|
||||
|
||||
module std::time::os @if(LINUX_LIBC);
|
||||
const CLOCK_REALTIME = 0;
|
||||
const CLOCK_MONOTONIC = 1;
|
||||
const CLOCK_PROCESS_CPUTIME_ID = 2;
|
||||
@@ -65,24 +79,4 @@ const CLOCK_BOOTTIME = 7;
|
||||
const CLOCK_REALTIME_ALARM = 8;
|
||||
const CLOCK_BOOTTIME_ALARM = 9;
|
||||
const CLOCK_TAI = 11;
|
||||
$endswitch
|
||||
|
||||
extern fn void clock_gettime(int type, TimeSpec *time);
|
||||
|
||||
fn Time native_timestamp()
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64);
|
||||
}
|
||||
|
||||
$if !env::os_is_darwin():
|
||||
fn Clock native_clock()
|
||||
{
|
||||
TimeSpec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns);
|
||||
}
|
||||
$endif
|
||||
|
||||
$endif
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
module std::time::os;
|
||||
module std::time::os @if(WIN32_LIBC);
|
||||
import std::os::win32;
|
||||
|
||||
$if env::os_is_win32() && env::COMPILER_LIBC_AVAILABLE:
|
||||
|
||||
extern fn void win32_GetSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime");
|
||||
extern fn Win32_BOOL win32_QueryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency");
|
||||
extern fn Win32_BOOL win32_QueryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter");
|
||||
@@ -28,6 +26,4 @@ fn Time native_timestamp()
|
||||
win32_GetSystemTimeAsFileTime(&ft);
|
||||
ulong result = (ulong)ft.dwHighDateTime << 32 | ft.dwLowDateTime;
|
||||
return (Time)(result / WINDOWS_TICK_US - WIN_TO_UNIX_EPOCH_US);
|
||||
}
|
||||
|
||||
$endif
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
module std::time;
|
||||
|
||||
def Time @inline = distinct long;
|
||||
def TimeDuration @inline = distinct long;
|
||||
def Clock @inline = distinct ulong;
|
||||
def NanoDuration @inline = distinct long;
|
||||
def Time = distinct long @inline;
|
||||
def TimeDuration = distinct long @inline;
|
||||
def Clock = distinct ulong @inline;
|
||||
def NanoDuration = distinct long @inline;
|
||||
|
||||
const TimeDuration MICROSECONDS_PER_SECOND = 1_000_000;
|
||||
const TimeDuration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;
|
||||
@@ -61,11 +61,11 @@ enum Month : char
|
||||
|
||||
fn Time now()
|
||||
{
|
||||
$if $defined(native_timestamp):
|
||||
return os::native_timestamp();
|
||||
$else
|
||||
return 0;
|
||||
$endif
|
||||
$if $defined(native_timestamp):
|
||||
return os::native_timestamp();
|
||||
$else
|
||||
return 0;
|
||||
$endif
|
||||
}
|
||||
|
||||
fn Time Time.add_seconds(Time time, long seconds) => time + (Time)(seconds * (long)MICROSECONDS_PER_SECOND);
|
||||
|
||||
Reference in New Issue
Block a user