mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-22 06:15:20 +00:00
Merge pull request #4934 from laytan/vendor-libc-additions
vendor/libc: a bunch of additions
This commit is contained in:
33
vendor/libc/ctype.odin
vendored
Normal file
33
vendor/libc/ctype.odin
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package odin_libc
|
||||
|
||||
@(require, linkage="strong", link_name="isdigit")
|
||||
isdigit :: proc "c" (c: i32) -> b32 {
|
||||
switch c {
|
||||
case '0'..='9': return true
|
||||
case: return false
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isblank")
|
||||
isblank :: proc "c" (c: i32) -> b32 {
|
||||
switch c {
|
||||
case '\t', ' ': return true
|
||||
case: return false
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isspace")
|
||||
isspace :: proc "c" (c: i32) -> b32 {
|
||||
switch c {
|
||||
case '\t', ' ', '\n', '\v', '\f', '\r': return true
|
||||
case: return false
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="toupper")
|
||||
toupper :: proc "c" (c: i32) -> i32 {
|
||||
if c >= 'a' && c <= 'z' {
|
||||
return c - ('a' - 'A')
|
||||
}
|
||||
return c
|
||||
}
|
||||
21
vendor/libc/include/alloca.h
vendored
Normal file
21
vendor/libc/include/alloca.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *alloca(size_t); /* built-in for gcc */
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
/* built-in for gcc 3 */
|
||||
#undef alloca
|
||||
#undef __alloca
|
||||
#define alloca(size) __alloca(size)
|
||||
#define __alloca(size) __builtin_alloca(size)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
12
vendor/libc/include/assert.h
vendored
12
vendor/libc/include/assert.h
vendored
@@ -1,3 +1,9 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(e) ((void)0)
|
||||
#else
|
||||
@@ -14,3 +20,9 @@ void __odin_libc_assert_fail(const char *, const char *, int, const char *);
|
||||
(__builtin_expect(!(e), 0) ? __odin_libc_assert_fail(__func__, __ASSERT_FILE_NAME, __LINE__, #e) : (void)0)
|
||||
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#define static_assert _Static_assert
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
15
vendor/libc/include/ctype.h
vendored
Normal file
15
vendor/libc/include/ctype.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
int isdigit(int c);
|
||||
int isblank(int c);
|
||||
int isspace(int c);
|
||||
|
||||
int toupper(int c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
0
vendor/libc/include/inttypes.h
vendored
Normal file
0
vendor/libc/include/inttypes.h
vendored
Normal file
49
vendor/libc/include/math.h
vendored
49
vendor/libc/include/math.h
vendored
@@ -1,21 +1,66 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define INFINITY (1.0 / 0.0)
|
||||
#define NAN (0.0 / 0.0)
|
||||
|
||||
float sqrtf(float);
|
||||
float cosf(float);
|
||||
float sinf(float);
|
||||
float atan2f(float, float);
|
||||
bool isnan(float);
|
||||
bool isinf(float);
|
||||
|
||||
float floorf(float x);
|
||||
double floor(double x);
|
||||
float ceilf(float x);
|
||||
double ceil(double x);
|
||||
double sqrt(double x);
|
||||
float powf(float x, float y);
|
||||
double pow(double x, double y);
|
||||
float fmodf(float x, float y);
|
||||
double fmod(double x, double y);
|
||||
double cos(double x);
|
||||
float acosf(float x);
|
||||
double acos(double x);
|
||||
float fabsf(float x);
|
||||
double fabs(double x);
|
||||
int abs(int);
|
||||
double ldexp(double, int);
|
||||
double exp(double);
|
||||
float logf(float);
|
||||
double log(double);
|
||||
double sin(double);
|
||||
double trunc(double);
|
||||
double log2(double);
|
||||
double log10(double);
|
||||
double asin(double);
|
||||
double atan(double);
|
||||
double tan(double);
|
||||
double atan2(double, double);
|
||||
double modf(double, double*);
|
||||
|
||||
bool __isnanf(float);
|
||||
bool __isnand(double);
|
||||
#define isnan(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isnanf((float)(x)) \
|
||||
: : __isnand((double)(x)))
|
||||
|
||||
bool __isinff(float);
|
||||
bool __isinfd(double);
|
||||
#define isinf(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isinff((float)(x)) \
|
||||
: : __isinfd((double)(x)))
|
||||
|
||||
bool __isfinitef(float);
|
||||
bool __isfinited(double);
|
||||
#define isfinite(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isfinitef((float)(x)) \
|
||||
: : __isfinited((double)(x)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
58
vendor/libc/include/stdio.h
vendored
58
vendor/libc/include/stdio.h
vendored
@@ -1,8 +1,14 @@
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {} FILE;
|
||||
|
||||
#define SEEK_SET 0
|
||||
@@ -12,6 +18,8 @@ typedef struct {} FILE;
|
||||
#define stdout ((FILE *)2)
|
||||
#define stderr ((FILE *)3)
|
||||
|
||||
#define EOF -1
|
||||
|
||||
FILE *fopen(const char *, char *);
|
||||
int fclose(FILE *);
|
||||
int fseek(FILE *, long, int);
|
||||
@@ -21,6 +29,10 @@ size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
|
||||
int vfprintf(FILE *, const char *, va_list);
|
||||
int vsnprintf(char *, size_t, const char *, va_list);
|
||||
int vsprintf(char *, const char *, va_list);
|
||||
|
||||
int putchar(int ch);
|
||||
int getchar();
|
||||
|
||||
static inline int snprintf(char *buf, size_t size, const char *fmt, ...) {
|
||||
va_list args;
|
||||
@@ -30,6 +42,14 @@ static inline int snprintf(char *buf, size_t size, const char *fmt, ...) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int sprintf(char *buf, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int result = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int fprintf(FILE *f, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -45,3 +65,37 @@ static inline int printf(const char *fmt, ...) {
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int __sscanf(const char *str, const char *format, void *ptrs);
|
||||
|
||||
static inline int vsscanf(const char *str, const char *format, va_list ap) {
|
||||
int count = 0;
|
||||
for (int i = 0; format[i]; i++) {
|
||||
if (format[i] == '%') {
|
||||
if (format[i+1] == '%') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
void **ptrs = (void **)(alloca(count*sizeof(void *)));
|
||||
for (int i = 0; i < count; i++) {
|
||||
ptrs[i] = va_arg(ap, void *);
|
||||
}
|
||||
|
||||
return __sscanf(str, format, ptrs);
|
||||
}
|
||||
|
||||
static inline int sscanf(const char *str, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int res = vsscanf(str, format, args);
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
25
vendor/libc/include/stdlib.h
vendored
25
vendor/libc/include/stdlib.h
vendored
@@ -1,3 +1,9 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *malloc(size_t size);
|
||||
@@ -17,3 +23,22 @@ long long atoll(const char *);
|
||||
double atof(const char *);
|
||||
|
||||
long strtol(const char *, char **, int);
|
||||
double strtod(const char *, char **);
|
||||
|
||||
void abort();
|
||||
void exit(int exit_code);
|
||||
|
||||
#define ATEXIT_MAX 32
|
||||
|
||||
int atexit(typeof(void (void)) *);
|
||||
|
||||
typedef struct {
|
||||
long int quot;
|
||||
long int rem;
|
||||
} ldiv_t;
|
||||
|
||||
ldiv_t ldiv(long int number, long int denom);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
11
vendor/libc/include/string.h
vendored
11
vendor/libc/include/string.h
vendored
@@ -1,9 +1,16 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *memcpy(void *, const void *, size_t);
|
||||
void *memset(void *, int, size_t);
|
||||
void *memmove(void *, void *, size_t);
|
||||
int memcmp(const void *, const void *, size_t);
|
||||
void *memchr(const void *, int, size_t);
|
||||
|
||||
unsigned long strlen(const char *str);
|
||||
|
||||
@@ -19,3 +26,7 @@ int strcmp(const char *, const char *);
|
||||
int strncmp(const char *, const char *, size_t);
|
||||
|
||||
char *strstr(const char *, const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
16
vendor/libc/include/time.h
vendored
Normal file
16
vendor/libc/include/time.h
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int64_t clock_t;
|
||||
typedef clock_t time_t;
|
||||
|
||||
clock_t clock();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
124
vendor/libc/math.odin
vendored
124
vendor/libc/math.odin
vendored
@@ -14,23 +14,28 @@ cosf :: proc "c" (v: f32) -> f32 {
|
||||
return math.cos(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sinf")
|
||||
sinf :: proc "c" (v: f32) -> f32 {
|
||||
return math.sin(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atan2f")
|
||||
atan2f :: proc "c" (v: f32, v2: f32) -> f32 {
|
||||
return math.atan2(v, v2)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isnan")
|
||||
isnan :: proc "c" (v: f32) -> bool {
|
||||
@(require, linkage="strong", link_name="__isnanf")
|
||||
isnanf :: proc "c" (v: f32) -> bool {
|
||||
return math.is_nan(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="isinf")
|
||||
isinf :: proc "c" (v: f32) -> bool {
|
||||
@(require, linkage="strong", link_name="__isnand")
|
||||
isnand :: proc "c" (v: f64) -> bool {
|
||||
return math.is_nan(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="__isinff")
|
||||
isinff :: proc "c" (v: f32) -> bool {
|
||||
return math.is_inf(v)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="__isinfd")
|
||||
isinfd :: proc "c" (v: f64) -> bool {
|
||||
return math.is_inf(v)
|
||||
}
|
||||
|
||||
@@ -39,21 +44,41 @@ sqrt :: proc "c" (x: f64) -> f64 {
|
||||
return math.sqrt(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="floorf")
|
||||
floorf :: proc "c" (x: f32) -> f32 {
|
||||
return math.floor(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="floor")
|
||||
floor :: proc "c" (x: f64) -> f64 {
|
||||
return math.floor(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ceilf")
|
||||
ceilf :: proc "c" (x: f32) -> f32 {
|
||||
return math.ceil(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ceil")
|
||||
ceil :: proc "c" (x: f64) -> f64 {
|
||||
return math.ceil(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="powf")
|
||||
powf :: proc "c" (x, y: f32) -> f32 {
|
||||
return math.pow(x, y)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="pow")
|
||||
pow :: proc "c" (x, y: f64) -> f64 {
|
||||
return math.pow(x, y)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fmodf")
|
||||
fmodf :: proc "c" (x, y: f32) -> f32 {
|
||||
return math.mod(x, y)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fmod")
|
||||
fmod :: proc "c" (x, y: f64) -> f64 {
|
||||
return math.mod(x, y)
|
||||
@@ -64,11 +89,21 @@ cos :: proc "c" (x: f64) -> f64 {
|
||||
return math.cos(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="acosf")
|
||||
acosf :: proc "c" (x: f32) -> f32 {
|
||||
return math.acos(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="acos")
|
||||
acos :: proc "c" (x: f64) -> f64 {
|
||||
return math.acos(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fabsf")
|
||||
fabsf :: proc "c" (x: f32) -> f32 {
|
||||
return math.abs(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fabs")
|
||||
fabs :: proc "c" (x: f64) -> f64 {
|
||||
return math.abs(x)
|
||||
@@ -89,6 +124,11 @@ exp :: proc "c" (x: f64) -> f64 {
|
||||
return math.exp(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="logf")
|
||||
logf :: proc "c" (x: f32) -> f32 {
|
||||
return math.ln(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="log")
|
||||
log :: proc "c" (x: f64) -> f64 {
|
||||
return math.ln(x)
|
||||
@@ -98,3 +138,69 @@ log :: proc "c" (x: f64) -> f64 {
|
||||
sin :: proc "c" (x: f64) -> f64 {
|
||||
return math.sin(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sinf")
|
||||
sinf :: proc "c" (v: f32) -> f32 {
|
||||
return math.sin(v)
|
||||
}
|
||||
|
||||
|
||||
@(require, linkage="strong", link_name="trunc")
|
||||
trunc :: proc "c" (x: f64) -> f64 {
|
||||
return math.trunc(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="__isfinitef")
|
||||
isfinitef :: proc "c" (x: f32) -> bool {
|
||||
switch math.classify(x) {
|
||||
case .Normal, .Subnormal, .Zero, .Neg_Zero: return true
|
||||
case .Inf, .Neg_Inf, .NaN: return false
|
||||
case: unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="__isfinited")
|
||||
isfinited :: proc "c" (x: f64) -> bool {
|
||||
switch math.classify(x) {
|
||||
case .Normal, .Subnormal, .Zero, .Neg_Zero: return true
|
||||
case .Inf, .Neg_Inf, .NaN: return false
|
||||
case: unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="log2")
|
||||
log2 :: proc "c" (x: f64) -> f64 {
|
||||
return math.log2(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="log10")
|
||||
log10 :: proc "c" (x: f64) -> f64 {
|
||||
return math.log10(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="asin")
|
||||
asin :: proc "c" (x: f64) -> f64 {
|
||||
return math.asin(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atan")
|
||||
atan :: proc "c" (x: f64) -> f64 {
|
||||
return math.atan(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="tan")
|
||||
tan :: proc "c" (x: f64) -> f64 {
|
||||
return math.tan(x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="atan2")
|
||||
atan2 :: proc "c" (y: f64, x: f64) -> f64 {
|
||||
return math.atan2(y, x)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="modf")
|
||||
modf :: proc "c" (num: f64, iptr: ^f64) -> f64 {
|
||||
integral, fractional := math.modf(num)
|
||||
iptr^ = integral
|
||||
return fractional
|
||||
}
|
||||
|
||||
413
vendor/libc/stdio.odin
vendored
413
vendor/libc/stdio.odin
vendored
@@ -1,18 +1,23 @@
|
||||
#+build !freestanding
|
||||
package odin_libc
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
import "core:c"
|
||||
import "core:io"
|
||||
import "core:os"
|
||||
import "core:strconv"
|
||||
|
||||
import stb "vendor:stb/sprintf"
|
||||
|
||||
FILE :: uintptr
|
||||
|
||||
EOF :: -1
|
||||
|
||||
@(require, linkage="strong", link_name="fopen")
|
||||
fopen :: proc "c" (path: cstring, mode: cstring) -> FILE {
|
||||
context = g_ctx
|
||||
unimplemented("odin_libc.fopen")
|
||||
unimplemented("vendor/libc: fopen")
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="fseek")
|
||||
@@ -63,6 +68,31 @@ fwrite :: proc "c" (buffer: [^]byte, size: uint, count: uint, file: FILE) -> uin
|
||||
return uint(max(0, n))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="putchar")
|
||||
putchar :: proc "c" (char: c.int) -> c.int {
|
||||
context = g_ctx
|
||||
|
||||
n, err := os.write_byte(os.stdout, byte(char))
|
||||
if n == 0 || err != nil {
|
||||
return EOF
|
||||
}
|
||||
return char
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="getchar")
|
||||
getchar :: proc "c" () -> c.int {
|
||||
when #defined(os.stdin) {
|
||||
ret: [1]byte
|
||||
n, err := os.read(os.stdin, ret[:])
|
||||
if n == 0 || err != nil {
|
||||
return EOF
|
||||
}
|
||||
return c.int(ret[0])
|
||||
} else {
|
||||
return EOF
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="vsnprintf")
|
||||
vsnprintf :: proc "c" (buf: [^]byte, count: uint, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
i32_count := i32(count)
|
||||
@@ -70,6 +100,11 @@ vsnprintf :: proc "c" (buf: [^]byte, count: uint, fmt: cstring, args: ^c.va_list
|
||||
return stb.vsnprintf(buf, i32_count, fmt, args)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="vsprintf")
|
||||
vsprintf :: proc "c" (buf: [^]byte, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
return stb.vsprintf(buf, fmt, args)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="vfprintf")
|
||||
vfprintf :: proc "c" (file: FILE, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
context = g_ctx
|
||||
@@ -105,3 +140,379 @@ vfprintf :: proc "c" (file: FILE, fmt: cstring, args: ^c.va_list) -> i32 {
|
||||
|
||||
return i32(len(buf))
|
||||
}
|
||||
|
||||
/*
|
||||
Derived from musl libc - MIT licensed - Copyright © 2005-2020 Rich Felker, et al.
|
||||
*/
|
||||
@(require, linkage="strong", link_name="__sscanf")
|
||||
_sscanf :: proc "c" (str, fmt: [^]byte, orig_ptrs: [^]rawptr) -> i32 {
|
||||
Size :: enum u8 {
|
||||
None,
|
||||
hh,
|
||||
h,
|
||||
l,
|
||||
L,
|
||||
ll,
|
||||
}
|
||||
|
||||
store_int :: proc(dest: rawptr, size: Size, i: u64) {
|
||||
if dest == nil { return }
|
||||
#partial switch size {
|
||||
case .hh:
|
||||
(^c.char)(dest)^ = c.char(i)
|
||||
case .h:
|
||||
(^c.short)(dest)^ = c.short(i)
|
||||
case .None:
|
||||
(^c.int)(dest)^ = c.int(i)
|
||||
case .l:
|
||||
(^c.long)(dest)^ = c.long(i)
|
||||
case .ll:
|
||||
(^c.longlong)(dest)^ = c.longlong(i)
|
||||
}
|
||||
}
|
||||
|
||||
context = g_ctx
|
||||
|
||||
str := str
|
||||
ptrs := orig_ptrs
|
||||
|
||||
// TODO: implement wide char variants
|
||||
|
||||
pos: u64
|
||||
dest: rawptr
|
||||
ch, t: byte
|
||||
// wcs: [^]c.wchar_t
|
||||
s: [^]byte
|
||||
k, i, width: int
|
||||
alloc: bool
|
||||
scanset: [257]byte
|
||||
invert: u8
|
||||
matches: i32
|
||||
size: Size
|
||||
input_fail, match_fail, fmt_fail, alloc_fail: bool
|
||||
|
||||
main_loop: for p := fmt; p[0] != 0; p = p[1:] {
|
||||
alloc = false
|
||||
|
||||
if isspace(i32(p[0])) {
|
||||
for isspace(i32(p[0])) {
|
||||
p = p[1:]
|
||||
}
|
||||
for isspace(i32(str[0])) {
|
||||
str = str[1:]
|
||||
pos += 1
|
||||
}
|
||||
}
|
||||
|
||||
if p[0] != '%' || p[1] == '%' {
|
||||
if p[0] == '%' {
|
||||
p = p[1:]
|
||||
}
|
||||
ch = str[0]
|
||||
if ch != p[0] {
|
||||
if ch == 0 {
|
||||
input_fail = true
|
||||
break
|
||||
}
|
||||
match_fail = true
|
||||
break
|
||||
}
|
||||
pos += 1
|
||||
continue
|
||||
}
|
||||
|
||||
p = p[1:]
|
||||
if p[0] == '*' {
|
||||
dest = nil
|
||||
p = p[1:]
|
||||
} else if isdigit(i32(p[0])) && p[1] == '$' {
|
||||
dest = orig_ptrs[p[0] - '0']
|
||||
p = p[2:]
|
||||
} else {
|
||||
dest = ptrs[0]
|
||||
ptrs = ptrs[1:]
|
||||
}
|
||||
|
||||
for width = 0; isdigit(i32(p[0])); p = p[1:] {
|
||||
width = 10 * width + int(p[0] - '0')
|
||||
}
|
||||
|
||||
if p[0] == 'm' {
|
||||
// wcs = nil
|
||||
s = nil
|
||||
alloc = dest != nil
|
||||
p = p[1:]
|
||||
} else {
|
||||
alloc = false
|
||||
}
|
||||
|
||||
size = .None
|
||||
p = p[1:]
|
||||
switch p[-1] {
|
||||
case 'h':
|
||||
size = .h
|
||||
if p[0] == 'h' {
|
||||
p = p[1:]
|
||||
size = .hh
|
||||
}
|
||||
case 'l':
|
||||
size = .l
|
||||
if p[0] == 'l' {
|
||||
p = p[1:]
|
||||
size = .ll
|
||||
}
|
||||
case 'j':
|
||||
size = .ll
|
||||
case 'z', 't':
|
||||
size = .l
|
||||
case 'L':
|
||||
size = .L
|
||||
case 'd', 'i', 'o', 'u', 'x',
|
||||
'a', 'e', 'f', 'g',
|
||||
'A', 'E', 'F', 'G', 'X',
|
||||
's', 'c', '[',
|
||||
'S', 'C', 'p', 'n':
|
||||
p = p[-1:]
|
||||
case:
|
||||
fmt_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
t = p[0]
|
||||
|
||||
switch t {
|
||||
case 'C':
|
||||
t = 'c'
|
||||
size = .l
|
||||
case 'S':
|
||||
t = 's'
|
||||
size = .l
|
||||
}
|
||||
|
||||
switch t {
|
||||
case 'c':
|
||||
if width < 1 {
|
||||
width = 1
|
||||
}
|
||||
case '[':
|
||||
case 'n':
|
||||
store_int(dest, size, pos)
|
||||
continue
|
||||
case:
|
||||
for isspace(i32(str[0])) {
|
||||
str = str[1:]
|
||||
pos += 1
|
||||
}
|
||||
}
|
||||
|
||||
if str[0] == 0 {
|
||||
input_fail = true
|
||||
break
|
||||
}
|
||||
|
||||
if width == 0 {
|
||||
width = max(int)
|
||||
}
|
||||
|
||||
switch t {
|
||||
case 's', 'c', '[':
|
||||
if t == 'c' || t == 's' {
|
||||
runtime.memset(&scanset, -1, size_of(scanset))
|
||||
scanset[0] = 0
|
||||
if t == 's' {
|
||||
scanset['\t'] = 0
|
||||
scanset['\n'] = 0
|
||||
scanset['\v'] = 0
|
||||
scanset['\f'] = 0
|
||||
scanset['\r'] = 0
|
||||
scanset[' '] = 0
|
||||
}
|
||||
} else {
|
||||
p = p[1:]
|
||||
invert = 0
|
||||
if p[0] == '^' {
|
||||
p = p[1:]
|
||||
invert = 1
|
||||
}
|
||||
|
||||
runtime.memset(&scanset, i32(invert), size_of(scanset))
|
||||
scanset[0] = 0
|
||||
if p[0] == '-' {
|
||||
p = p[1:]
|
||||
scanset['-'] = 1 - invert
|
||||
} else if p[0] == ']' {
|
||||
p = p[1:]
|
||||
scanset[']'] = 1 - invert
|
||||
}
|
||||
|
||||
for ; p[0] != ']'; p = p[1:] {
|
||||
if p[0] == 0 {
|
||||
fmt_fail = true
|
||||
break main_loop
|
||||
}
|
||||
if p[0] == '-' && p[1] != ']' {
|
||||
c := p
|
||||
p = p[1:]
|
||||
for ch = c[0]; c[0] < p[0]; c, ch = c[1:], c[0] {
|
||||
scanset[ch] = 1 - invert
|
||||
}
|
||||
scanset[p[0]] = 1 - invert
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wcs = nil
|
||||
s = nil
|
||||
i = 0
|
||||
k = t == 'c' ? width + 1 : 31
|
||||
if size == .l {
|
||||
unimplemented("vendor/libc: sscanf wide character support")
|
||||
} else if alloc {
|
||||
s = make([^]byte, k)
|
||||
if s == nil {
|
||||
alloc_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
for ch = str[0]; scanset[ch] != 0 && i < width; {
|
||||
s[i] = ch
|
||||
i += 1
|
||||
if i == k {
|
||||
old_size := k
|
||||
k += k + 1
|
||||
tmp, _ := runtime.non_zero_mem_resize(s, old_size, k)
|
||||
if tmp == nil {
|
||||
alloc_fail = true
|
||||
break main_loop
|
||||
}
|
||||
s = raw_data(tmp)
|
||||
}
|
||||
|
||||
str = str[1:]
|
||||
ch = str[0]
|
||||
}
|
||||
} else {
|
||||
s = cast([^]byte)dest
|
||||
if s != nil {
|
||||
for ch = str[0]; scanset[ch] != 0 && i < width; {
|
||||
s[i] = ch
|
||||
i += 1
|
||||
|
||||
str = str[1:]
|
||||
ch = str[0]
|
||||
}
|
||||
} else {
|
||||
for ; scanset[str[0]] != 0 && i < width; str = str[1:] {}
|
||||
}
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
match_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
str = str[-1:]
|
||||
|
||||
if t == 'c' && i != width {
|
||||
match_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
if alloc {
|
||||
(^rawptr)(dest)^ = s
|
||||
}
|
||||
|
||||
if t != 'c' {
|
||||
if s != nil {s[i] = 0}
|
||||
}
|
||||
case:
|
||||
base := -1
|
||||
switch t {
|
||||
case 'p', 'X', 'x':
|
||||
base = 16
|
||||
if i + 2 < width && str[0] == '0' && str[1] == 'x' {
|
||||
str = str[2:]
|
||||
}
|
||||
case 'o':
|
||||
base = 8
|
||||
if i + 1 < width && str[0] == '0' {
|
||||
str = str[1:]
|
||||
}
|
||||
case 'd', 'u':
|
||||
base = 10
|
||||
case 'i':
|
||||
base = 0
|
||||
}
|
||||
|
||||
odin_str := string(cstring(str))
|
||||
odin_str = odin_str[:min(len(odin_str), width-i)]
|
||||
cnt: int
|
||||
if base >= 0 {
|
||||
x: i64
|
||||
if base == 0 {
|
||||
x, _ = strconv.parse_i64_maybe_prefixed(odin_str, &cnt)
|
||||
} else {
|
||||
x, _ = strconv.parse_i64_of_base(odin_str, base, &cnt)
|
||||
}
|
||||
|
||||
if cnt == 0 {
|
||||
match_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
if t == 'p' && dest != nil {
|
||||
(^rawptr)(dest)^ = rawptr(uintptr(x))
|
||||
} else {
|
||||
store_int(dest, size, u64(x))
|
||||
}
|
||||
} else {
|
||||
// should be a guarantee bcs of validation above.
|
||||
// switch t {
|
||||
// case 'a', 'A',
|
||||
// 'e', 'E',
|
||||
// 'f', 'F',
|
||||
// 'g', 'G':
|
||||
// }
|
||||
x, _ := strconv.parse_f64(odin_str, &cnt)
|
||||
|
||||
if cnt == 0 {
|
||||
match_fail = true
|
||||
break main_loop
|
||||
}
|
||||
|
||||
if dest != nil {
|
||||
#partial switch size {
|
||||
case .None:
|
||||
(^c.float)(dest)^ = c.float(x)
|
||||
case .l:
|
||||
(^c.double)(dest)^ = c.double(x)
|
||||
case .L:
|
||||
(^c.double)(dest)^ = c.double(x) // longdouble
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += u64(cnt)
|
||||
str = str[cnt:]
|
||||
}
|
||||
|
||||
if dest != nil {
|
||||
matches += 1
|
||||
}
|
||||
}
|
||||
|
||||
if fmt_fail || alloc_fail || input_fail {
|
||||
if matches == 0 {
|
||||
matches = -1
|
||||
}
|
||||
}
|
||||
|
||||
if match_fail {
|
||||
if alloc {
|
||||
free(s)
|
||||
// free(wcs)
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
73
vendor/libc/stdlib.odin
vendored
73
vendor/libc/stdlib.odin
vendored
@@ -1,8 +1,10 @@
|
||||
package odin_libc
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
|
||||
import "core:c"
|
||||
import "core:os"
|
||||
import "core:slice"
|
||||
import "core:sort"
|
||||
import "core:strconv"
|
||||
@@ -108,12 +110,81 @@ atof :: proc "c" (str: cstring) -> f64 {
|
||||
@(require, linkage="strong", link_name="strtol")
|
||||
strtol :: proc "c" (str: cstring, str_end: ^cstring, base: i32) -> c.long {
|
||||
context = g_ctx
|
||||
|
||||
sstr := string(str)
|
||||
sstr = strings.trim_left_space(sstr)
|
||||
|
||||
n: int
|
||||
i, _ := strconv.parse_i64_of_base(sstr, int(base), &n)
|
||||
str_end ^= cstring(raw_data(sstr)[n:])
|
||||
if str_end != nil {
|
||||
str_end ^= cstring(raw_data(sstr)[n:])
|
||||
}
|
||||
return c.long(clamp(i, i64(min(c.long)), i64(max(c.long))))
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="strtod")
|
||||
strtod :: proc "c" (str: cstring, str_end: ^cstring) -> c.double {
|
||||
context = g_ctx
|
||||
|
||||
sstr := string(str)
|
||||
sstr = strings.trim_left_space(sstr)
|
||||
|
||||
n: int
|
||||
val, _ := strconv.parse_f64(sstr, &n)
|
||||
if str_end != nil {
|
||||
str_end ^= cstring(raw_data(sstr)[n:])
|
||||
}
|
||||
|
||||
return c.double(val)
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="abort")
|
||||
abort :: proc "c" () -> ! {
|
||||
intrinsics.trap()
|
||||
}
|
||||
|
||||
ATEXIT_MAX :: 32
|
||||
|
||||
@(private)
|
||||
atexit_functions: [ATEXIT_MAX]proc "c" ()
|
||||
@(private)
|
||||
atexit_functions_count: int
|
||||
|
||||
@(require, linkage="strong", link_name="atexit")
|
||||
atexit :: proc "c" (function: proc "c" ()) -> i32 {
|
||||
entry := intrinsics.atomic_add(&atexit_functions_count, 1)
|
||||
if entry >= ATEXIT_MAX {
|
||||
return -1
|
||||
}
|
||||
|
||||
atexit_functions[entry] = function
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@(require, linkage="strong", link_name="exit")
|
||||
exit :: proc "c" (exit_code: c.int) -> ! {
|
||||
finish_atexit()
|
||||
os.exit(int(exit_code))
|
||||
}
|
||||
|
||||
@(private, fini)
|
||||
finish_atexit :: proc "c" () {
|
||||
n := intrinsics.atomic_exchange(&atexit_functions_count, 0)
|
||||
for function in atexit_functions[:n] {
|
||||
function()
|
||||
}
|
||||
}
|
||||
|
||||
ldiv_t :: struct {
|
||||
quot: c.long,
|
||||
rem: c.long,
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="ldiv")
|
||||
ldiv :: proc "c" (number: c.long, denom: c.long) -> ldiv_t {
|
||||
return {
|
||||
quot = number / denom,
|
||||
rem = number %% denom,
|
||||
}
|
||||
}
|
||||
|
||||
10
vendor/libc/string.odin
vendored
10
vendor/libc/string.odin
vendored
@@ -5,6 +5,7 @@ import "base:intrinsics"
|
||||
import "core:c"
|
||||
import "core:strings"
|
||||
import "core:mem"
|
||||
import "core:bytes"
|
||||
|
||||
// NOTE: already defined by Odin.
|
||||
// void *memcpy(void *, const void *, size_t);
|
||||
@@ -109,3 +110,12 @@ strstr :: proc "c" (str: cstring, substr: cstring) -> cstring {
|
||||
return cstring(([^]byte)(str)[idx:])
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="memchr")
|
||||
memchr :: proc "c" (str: [^]byte, c: i32, n: uint) -> [^]byte {
|
||||
idx := bytes.index_byte(str[:n], u8(c))
|
||||
if idx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return str[idx:]
|
||||
}
|
||||
|
||||
10
vendor/libc/time.odin
vendored
Normal file
10
vendor/libc/time.odin
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package odin_libc
|
||||
|
||||
import "core:time"
|
||||
|
||||
clock_t :: i64
|
||||
|
||||
@(require, linkage="strong", link_name="clock")
|
||||
clock :: proc "c" () -> clock_t {
|
||||
return time.tick_now()._nsec
|
||||
}
|
||||
Reference in New Issue
Block a user