From ad48770977962e9bce3300c73710321ec05d9a8a Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 6 Jan 2023 01:26:46 +0100 Subject: [PATCH] Updated errno. Socket constants and some functions added. Fix error when a macro returns a void! and that macro is in turn set to a return. Removed too permissive casts to subarrays. --- lib/std/core/str.c3 | 44 +++++++++-- lib/std/libc/libc.c3 | 3 + lib/std/net/ipproto.c3 | 104 ++++++++++++++++++++++++++ lib/std/net/net.c3 | 9 +++ lib/std/net/os/common.c3 | 18 +++++ lib/std/net/os/darwin.c3 | 67 +++++++++++++++++ lib/std/net/os/linux.c3 | 32 ++++++++ lib/std/net/os/posix.c3 | 42 +++++++++++ lib/std/net/os/win32.c3 | 33 ++++++++ lib/std/net/sock.c3 | 7 ++ lib/std/os/win32/error.c3 | 29 +++++++ src/compiler/llvm_codegen_c_abi_x64.c | 2 +- src/compiler/llvm_codegen_function.c | 3 +- src/compiler/sema_casts.c | 2 +- src/compiler/sema_expr.c | 2 +- src/version.h | 2 +- 16 files changed, 388 insertions(+), 11 deletions(-) create mode 100644 lib/std/net/ipproto.c3 create mode 100644 lib/std/net/net.c3 create mode 100644 lib/std/net/os/common.c3 create mode 100644 lib/std/net/os/darwin.c3 create mode 100644 lib/std/net/os/linux.c3 create mode 100644 lib/std/net/os/posix.c3 create mode 100644 lib/std/net/os/win32.c3 create mode 100644 lib/std/net/sock.c3 create mode 100644 lib/std/os/win32/error.c3 diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 index 31ed37ee5..b34e0c9a6 100644 --- a/lib/std/core/str.c3 +++ b/lib/std/core/str.c3 @@ -50,7 +50,7 @@ private macro char_is_space_tab(char c) return c == ' ' || c == '\t'; } -private macro to_signed_integer($Type, char[] string) +private macro to_integer($Type, char[] string) { usz len = string.len; usz index = 0; @@ -121,11 +121,17 @@ private macro to_signed_integer($Type, char[] string) return value; } -fn int128! to_int128(char[] string) = to_signed_integer(int128, string); -fn long! to_long(char[] string) = to_signed_integer(long, string); -fn int! to_int(char[] string) = to_signed_integer(int, string); -fn short! to_short(char[] string) = to_signed_integer(short, string); -fn ichar! to_ichar(char[] string) = to_signed_integer(ichar, string); +fn int128! to_int128(char[] string) = to_integer(int128, string); +fn long! to_long(char[] string) = to_integer(long, string); +fn int! to_int(char[] string) = to_integer(int, string); +fn short! to_short(char[] string) = to_integer(short, string); +fn ichar! to_ichar(char[] string) = to_integer(ichar, string); + +fn uint128! to_uint128(char[] str) = to_integer(uint128, str); +fn ulong! to_ulong(char[] str) = to_integer(ulong, str); +fn uint! to_uint(char[] str) = to_integer(uint, str); +fn ushort! to_ushort(char[] str) = to_integer(ushort, str); +fn char! to_uchar(char[] str) = to_integer(char, str); fn char[] trim(char[] string, char[] to_trim = "\t\n\r ") { @@ -179,6 +185,32 @@ fn char[][] split(char[] s, char[] needle, Allocator* allocator = mem::current_a return holder[:i]; } +fn usz! rindex_of(char[] s, char[] needle) +{ + usz match = 0; + usz needed = needle.len; + if (!needed) return SearchResult.MISSING!; + usz index_start = 0; + char search = needle[0]; + foreach_r (usz i, char c : s) + { + if (c == search) + { + if (!match) index_start = i; + match++; + if (match == needed) return index_start; + search = needle[match]; + continue; + } + if (match) + { + match = 0; + search = needle[0]; + } + } + return SearchResult.MISSING!; +} + fn usz! index_of(char[] s, char[] needle) { usz match = 0; diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index 569808377..87e48b0f4 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -394,16 +394,19 @@ $if (env::OS_TYPE == OsType.MACOSX): 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 $elif (env::OS_TYPE == OsType.WIN32): 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 $else: 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 $endif; /* diff --git a/lib/std/net/ipproto.c3 b/lib/std/net/ipproto.c3 new file mode 100644 index 000000000..370274bc2 --- /dev/null +++ b/lib/std/net/ipproto.c3 @@ -0,0 +1,104 @@ +module std::net; + +const IPPPOTO_IP = 0; +const IPPROTO_ICMP = 1; +const IPPROTO_IGMP = 2; +const IPPROTO_IPV4 = 4; +const IPPROTO_TCP = 6; +const IPPROTO_ST = 7; +const IPPROTO_EGP = 8; +const IPPROTO_PIGP = 9; +const IPPROTO_RCCMON = 10; +const IPPROTO_NVPII = 11; +const IPPROTO_PUP = 12; +const IPPROTO_ARGUS = 13; +const IPPROTO_EMCON = 14; +const IPPROTO_XNET = 15; +const IPPROTO_CHAOS = 16; +const IPPROTO_UDP = 17; +const IPPROTO_MUX = 18; +const IPPROTO_MEAS = 19; +const IPPROTO_HMP = 20; +const IPPROTO_PRM = 21; +const IPPROTO_IDP = 22; +const IPPROTO_TRUNK1 = 23; +const IPPROTO_TRUNK2 = 24; +const IPPROTO_LEAF1 = 25; +const IPPROTO_LEAF2 = 26; +const IPPROTO_RDP = 27; +const IPPROTO_IRTP = 28; +const IPPROTO_TP = 29; +const IPPROTO_BLT = 30; +const IPPROTO_NSP = 31; +const IPPROTO_INP = 32; +const IPPROTO_SEP = 33; +const IPPROTO_3PC = 34; +const IPPROTO_IDPR = 35; +const IPPROTO_XTP = 36; +const IPPROTO_DDP = 37; +const IPPROTO_CMTP = 38; +const IPPROTO_TPXX = 39; +const IPPROTO_IL = 40; +const IPPROTO_IPV6 = 41; +const IPPROTO_SDRP = 42; +const IPPROTO_ROUTING = 43; +const IPPROTO_FRAGMENT = 44; +const IPPROTO_IDRP = 45; +const IPPROTO_RSVP = 46; +const IPPROTO_GRE = 47; +const IPPROTO_MHRP = 48; +const IPPROTO_BHA = 49; +const IPPROTO_ESP = 50; +const IPPROTO_AH = 51; +const IPPROTO_INLSP = 52; +const IPPROTO_SWIPE = 53; +const IPPROTO_NHRP = 54; +const IPPROTO_ICMPV6 = 58; +const IPPROTO_NONE = 59; +const IPPROTO_DSTOPTS = 60; +const IPPROTO_AHIP = 61; +const IPPROTO_CFTP = 62; +const IPPROTO_HELLO = 63; +const IPPROTO_SATEXPAK = 64; +const IPPROTO_KRYPTOLAN = 65; +const IPPROTO_RVD = 66; +const IPPROTO_IPPC = 67; +const IPPROTO_ADFS = 68; +const IPPROTO_SATMON = 69; +const IPPROTO_VISA = 70; +const IPPROTO_IPCV = 71; +const IPPROTO_CPNX = 72; +const IPPROTO_CPHB = 73; +const IPPROTO_WSN = 74; +const IPPROTO_PVP = 75; +const IPPROTO_BRSATMON = 76; +const IPPROTO_ND = 77; +const IPPROTO_WBMON = 78; +const IPPROTO_WBEXPAK = 79; +const IPPROTO_EON = 80; +const IPPROTO_VMTP = 81; +const IPPROTO_SVMTP = 82; +const IPPROTO_VINES = 83; +const IPPROTO_TTP = 84; +const IPPROTO_IGP = 85; +const IPPROTO_DGP = 86; +const IPPROTO_TCF = 87; +const IPPROTO_IGRP = 88; +const IPPROTO_OSPFIGP = 89; +const IPPROTO_SRPC = 90; +const IPPROTO_LARP = 91; +const IPPROTO_MTP = 92; +const IPPROTO_AX25 = 93; +const IPPROTO_IPEIP = 94; +const IPPROTO_MICP = 95; +const IPPROTO_SCCSP = 96; +const IPPROTO_ETHERIP = 97; +const IPPROTO_ENCAP = 98; +const IPPROTO_APES = 99; +const IPPROTO_GMTP = 100; +const IPPROTO_PIM = 103; +const IPPROTO_IPCOMP = 108; +const IPPROTO_PGM = 113; +const IPPROTO_SCTP = 132; +const IPPROTO_DIVERT = 254; +const IPPROTO_RAW = 255; diff --git a/lib/std/net/net.c3 b/lib/std/net/net.c3 new file mode 100644 index 000000000..d26c1e793 --- /dev/null +++ b/lib/std/net/net.c3 @@ -0,0 +1,9 @@ +module std::net; + +fault NetError +{ + INVALID_URL, + URL_TOO_LONG, + INVALID_SOCKET, + GENERAL_ERROR, +} \ No newline at end of file diff --git a/lib/std/net/os/common.c3 b/lib/std/net/os/common.c3 new file mode 100644 index 000000000..6aee9cced --- /dev/null +++ b/lib/std/net/os/common.c3 @@ -0,0 +1,18 @@ +module std::net::os; + +$if ($defined(PLATFORM_AF_INET)): + +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 O_NONBLOCK = PLATFORM_O_NONBLOCK; + + +$endif; \ No newline at end of file diff --git a/lib/std/net/os/darwin.c3 b/lib/std/net/os/darwin.c3 new file mode 100644 index 000000000..013f2c851 --- /dev/null +++ b/lib/std/net/os/darwin.c3 @@ -0,0 +1,67 @@ +module std::net::os; +import libc; + +$if (env::OS_TYPE == OsType.MACOSX): + +const AI_NUMERICSERV = 0x1000; +const AI_ALL = 0x100; +const AI_V4MAPPED_CFG = 0x200; +const AI_ADDRCONFIG = 0x400; +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; +const int PLATFORM_AF_PUP = 4; +const int PLATFORM_AF_CHAOS = 5; +const int PLATFORM_AF_NS = 6; +const int PLATFORM_AF_ISO = 7; +const int PLATFORM_AF_ECMA = 8; +const int PLATFORM_AF_DATAKIT = 9; +const int PLATFORM_AF_CCITT = 10; +const int PLATFORM_AF_SNA = 11; +const int PLATFORM_AF_DECNET = 12; +const int PLATFORM_AF_DLI = 13; +const int PLATFORM_AF_LAT = 14; +const int PLATFORM_AF_HYLINK = 15; +const int PLATFORM_AF_APPLETALK = 16; +const int PLATFORM_AF_ROUTE = 17; +const int PLATFORM_AF_LINK = 18; +const int PLATFORM_PSEUDO_AF_XTP = 19; +const int PLATFORM_AF_COIP = 20; +const int PLATFORM_AF_CNT = 21; +const int PLATFORM_PSEUDO_AF_RTIP = 22; +const int PLATFORM_AF_IPX = 23; +const int PLATFORM_AF_SIP = 24; +const int PLATFORM_PSEUDO_AF_PIP = 25; +const int PLATFORM_AF_NDRV = 27; +const int PLATFORM_AF_ISDN = 28; +const int PLATFORM_PSEUDO_AF_KEY = 29; +const int PLATFORM_AF_INET6 = 30; +const int PLATFORM_AF_NATM = 31; +const int PLATFORM_AF_SYSTEM = 32; +const int PLATFORM_AF_NETBIOS = 33; +const int PLATFORM_AF_PPP = 34; +const int PLATFORM_PSEUDO_AF_HDRCMPLT = 35; +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; \ No newline at end of file diff --git a/lib/std/net/os/linux.c3 b/lib/std/net/os/linux.c3 new file mode 100644 index 000000000..692babbec --- /dev/null +++ b/lib/std/net/os/linux.c3 @@ -0,0 +1,32 @@ +module std::net::os; +import libc; + +$if (env::OS_TYPE == OsType.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; +const int PLATFORM_AF_IPX = 4; +const int PLATFORM_AF_APPLETALK = 5; +const int PLATFORM_AF_NETROM = 6; +const int PLATFORM_AF_BRIDGE = 7; +const int PLATFORM_AF_AAL5 = 8; +const int PLATFORM_AF_X25 = 9; +const int PLATFORM_AF_INET6 = 10; + +const PLATFORM_O_NONBLOCK = 0o4000; + +$endif; \ No newline at end of file diff --git a/lib/std/net/os/posix.c3 b/lib/std/net/os/posix.c3 new file mode 100644 index 000000000..8f0971f4e --- /dev/null +++ b/lib/std/net/os/posix.c3 @@ -0,0 +1,42 @@ +module std::net::os; +import libc; + +$if (env::OS_TYPE != OsType.WIN32 && $defined(AddrInfo)): + +const int F_GETFL = 3; +const int F_SETFL = 4; + +define NativeSocket = distinct int; + +extern fn NativeSocket socket(int af, int type, int protocol) @extname("socket"); +extern fn int getaddrinfo(ZString nodename, ZString servname, AddrInfo* hints, AddrInfo** res); +extern fn void freeaddrinfo(AddrInfo* addr); +extern fn int connect(NativeSocket, void*, usz); +extern fn int fcntl(NativeSocket socket, int cmd, ...) @extname("fcntl"); +extern fn int close(NativeSocket); + +macro void! NativeSocket.close(NativeSocket this) +{ + if (close(this)) + { + if (libc::errno() == errno::EBADF) return NetError.INVALID_SOCKET!; + return NetError.GENERAL_ERROR!; + } +} + +macro void! NativeSocket.set_non_blocking(NativeSocket this) +{ + int flags = fcntl(this, F_GETFL, 0); + if (fcntl(this, F_SETFL, flags | O_NONBLOCK) == -1) + { + if (libc::errno() == errno::EBADF) return NetError.INVALID_SOCKET!; + return NetError.GENERAL_ERROR!; + } +} + +macro bool NativeSocket.is_non_blocking(NativeSocket this) +{ + return fcntl(this, F_GETFL, 0) & O_NONBLOCK == O_NONBLOCK; +} + +$endif; diff --git a/lib/std/net/os/win32.c3 b/lib/std/net/os/win32.c3 new file mode 100644 index 000000000..b109e5f46 --- /dev/null +++ b/lib/std/net/os/win32.c3 @@ -0,0 +1,33 @@ +module std::net::os; + +$if (env::OS_TYPE == OsType.WIN32): + +const int PLATFORM_AF_INET = 1; +const int PLATFORM_AF_IPX = 6; +const int PLATFORM_AF_APPLETALK = 16; +const int PLATFORM_AF_NETBIOS = 17; +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; +} + +define NativeSocket = distinct uptr; + +extern fn int wsa_startup(int, void*) @extname("WSAStartup"); +extern fn int ioctlsocket(NativeSocket, long cmd, ulong *argp); +extern fn int closesocket(NativeSocket); + +macro NativeSocket.close(NativeSocket this) = closesocket(this); + +$endif; \ No newline at end of file diff --git a/lib/std/net/sock.c3 b/lib/std/net/sock.c3 new file mode 100644 index 000000000..f1effb678 --- /dev/null +++ b/lib/std/net/sock.c3 @@ -0,0 +1,7 @@ +module std::net; + +const int SOCK_STREAM = 1; // Stream +const int SOCK_DGRAM = 2; // Datagram +const int SOCK_RAW = 3; // Raw +const int SOCK_RDM = 4; // Reliably delivered +const int SOCK_SEQPACKET = 5; // Sequential packet diff --git a/lib/std/os/win32/error.c3 b/lib/std/os/win32/error.c3 new file mode 100644 index 000000000..31d9eee70 --- /dev/null +++ b/lib/std/os/win32/error.c3 @@ -0,0 +1,29 @@ +module std::os::win32::wsa; + +$if (env::OS_TYPE == OsType.WIN32): +extern fn int get_last_error() @extname("WSAGetLastError"); +extern fn void set_last_error(int error) @extname("WSASetLastError"); + +const int INVALID_HANDLE = 6; +const int NOT_ENOUGHT_MEMORY = 8; +const int INVALID_PARAMETER = 87; +const int OPERATION_ABORTED = 995; +const int IO_INCOMPLETE = 996; +const int IO_PENDING = 997; +const int EINTR = 10004; +const int EBADF = 10009; +const int ACCESS = 10013; +const int EFAULT = 10014; +const int EINVAL = 10022; +const int EMFILE = 10024; +const int EWOULDBLOCK = 10035; +const int EINPROGRESS = 10036; +const int EALREADY = 10037; +const int ENOTSOCK = 10038; +const int EDESTADDRREQ = 10039; +const int EMSGSIZE = 10040; +const int EPROTOTYPE = 10041; +const int ENOPROTOOPT = 10042; +const int EPROTONOSUPPORT = 10043; +const int ESOCKTNOSUPPORT = 10044; +$endif; \ No newline at end of file diff --git a/src/compiler/llvm_codegen_c_abi_x64.c b/src/compiler/llvm_codegen_c_abi_x64.c index dbbd1d58d..adb515294 100644 --- a/src/compiler/llvm_codegen_c_abi_x64.c +++ b/src/compiler/llvm_codegen_c_abi_x64.c @@ -207,7 +207,7 @@ void x64_classify_post_merge(ByteSize size, X64Class *lo_class, X64Class *hi_cla // If one is MEM => both is mem // If X87UP is not before X87 => mem // If size > 16 && first isn't SSE or any other is not SSEUP => mem - // If SSEUP is not preceeded by SSE/SSEUP => convert to SSE. + // If SSEUP is not preceded by SSE/SSEUP => convert to SSE. if (*hi_class == CLASS_MEMORY) goto DEFAULT_TO_MEMORY; if (size > 16 && (*lo_class != CLASS_SSE || *hi_class != CLASS_SSEUP)) goto DEFAULT_TO_MEMORY; if (*hi_class == CLASS_SSEUP && *lo_class != CLASS_SSE && *lo_class != CLASS_SSEUP) diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 499b1b698..f3ff18323 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -296,8 +296,9 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *optiona // In this case we use the optional as the actual return. if (prototype->is_optional) { - if (return_value && return_value->value) + if (return_value && return_value->type != type_void) { + assert(return_value->value); llvm_store_to_ptr_aligned(c, c->return_out, return_value, type_alloca_alignment(return_value->type)); } return_out = c->optional_out; diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index bb9e3fb46..96d415dcb 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1471,7 +1471,7 @@ CAST: static inline bool cast_pointer(SemaContext *context, Expr *expr, Type *from, Type *to, Type *to_type, bool add_optional, CastOptions options) { // pointer -> any, void* -> pointer pointer -> void* - if (to == type_any || to == type_voidptr || from == type_voidptr) return cast_with_optional(expr, to_type, add_optional); + if (to == type_any || to == type_voidptr || (from == type_voidptr && type_is_pointer(to))) return cast_with_optional(expr, to_type, add_optional); Type *pointee = from->pointer; bool is_explicit = options.is_explicit; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 854395ece..fff1a73fb 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6969,7 +6969,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr) case EXPR_ACCESS: if (expr->access_expr.ref->decl_kind == DECL_FUNC) { - SEMA_ERROR(expr, "A function name must be followed by '(' or preceeded by '&'."); + SEMA_ERROR(expr, "A function name must be followed by '(' or preceded by '&'."); return false; } if (expr->access_expr.ref->decl_kind == DECL_MACRO) diff --git a/src/version.h b/src/version.h index a907a1242..45fe15796 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.3" \ No newline at end of file +#define COMPILER_VERSION "0.4.4" \ No newline at end of file