stdio.h the beginning

This commit is contained in:
bumbread 2022-06-22 00:32:46 +11:00
parent 88ef3bf81f
commit 7cb9dc133f
7 changed files with 199 additions and 66 deletions

View File

@ -1,14 +1,10 @@
#pragma once #pragma once
#include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h>
typedef struct FILE FILE; typedef struct FILE FILE;
typedef int64_t fpos_t; typedef size_t fpos_t;
typedef struct div_t div_t;
typedef struct ldiv_t ldiv_t;
typedef struct lldiv_t lldiv_t;
#if !defined(NULL) #if !defined(NULL)
#define NULL ((void *)0) #define NULL ((void *)0)
@ -26,15 +22,12 @@ typedef struct lldiv_t lldiv_t;
#endif #endif
#endif #endif
#define _IOFBF 0x0000 #define _IONBF 0
#define _IOLBF 0x0040 #define _IOFBF 1
#define _IONBF 0x0004 #define _IOLBF 2
#define BUFSIZ 512 #define BUFSIZ 512
#define EOF (-1) #define EOF (-1)
#define FOPEN_MAX 1024
#define FOPEN_MAX 20
#ifdef _os_win #ifdef _os_win
#define FILENAME_MAX 260 #define FILENAME_MAX 260

View File

@ -5,6 +5,10 @@ typedef struct mbstate_t mbstate_t;
typedef uint16_t char16_t; typedef uint16_t char16_t;
typedef uint32_t char32_t; typedef uint32_t char32_t;
struct mbstate_t {
char filler[4];
};
size_t mbrtoc16(char16_t * restrict pc16, const char * restrict s, size_t n, mbstate_t * restrict ps); size_t mbrtoc16(char16_t * restrict pc16, const char * restrict s, size_t n, mbstate_t * restrict ps);
size_t c16rtomb(char * restrict s, char16_t c16, mbstate_t * restrict ps); size_t c16rtomb(char * restrict s, char16_t c16, mbstate_t * restrict ps);
size_t mbrtoc32(char32_t * restrict pc32, const char * restrict s, size_t n, mbstate_t * restrict ps); size_t mbrtoc32(char32_t * restrict pc32, const char * restrict s, size_t n, mbstate_t * restrict ps);

View File

@ -1,15 +1,18 @@
#pragma once #pragma once
// On linux this will be UTF-32, on windows it's UTF-16 (or maybe UCS-2?)
typedef struct mbstate_t mbstate_t; typedef struct mbstate_t mbstate_t;
typedef wchar_t wint_t; typedef wchar_t wint_t;
struct mbstate_t {
char filler[4];
};
#define WCHAR_MIN 0x0000 #define WCHAR_MIN 0x0000
#define WCHAR_MAX 0xffff #define WCHAR_MAX 0xffff
#ifndef WEOF #ifndef WEOF
#define WEOF 0 #define WEOF 0
#endif #endif
int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...); int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...);

View File

@ -10,3 +10,4 @@
void _setup_timer(void); void _setup_timer(void);
void _setup_eh(); void _setup_eh();
void _setup_heap(); void _setup_heap();
void _setup_io();

View File

@ -71,15 +71,11 @@ static char **get_command_args(int *argc_ptr) {
void mainCRTStartup() { void mainCRTStartup() {
// Initialize standard pipe handles
stdout = (FILE*) GetStdHandle(STD_OUTPUT_HANDLE);
stderr = (FILE*) GetStdHandle(STD_ERROR_HANDLE);
stdin = (FILE*) GetStdHandle(STD_INPUT_HANDLE);
// Set-up some platform stuff // Set-up some platform stuff
_setup_heap();
_setup_eh(); _setup_eh();
_setup_heap();
_setup_timer(); _setup_timer();
_setup_io();
// Set-up CRT stuff // Set-up CRT stuff
srand(0); srand(0);
@ -145,3 +141,45 @@ char *getenv(const char *name) {
GetEnvironmentVariable(name, env_string, env_length); GetEnvironmentVariable(name, env_string, env_length);
return env_string; return env_string;
} }
int system(const char* string) {
int wchars_required = MultiByteToWideChar(65001, 0, string, -1, NULL, 0);
wchar_t* cmd_line = malloc(sizeof(L"cmd.exe ") + (wchars_required * sizeof(wchar_t)));
if (cmd_line == NULL) {
goto error;
}
memcpy(cmd_line, L"cmd.exe ", sizeof(L"cmd.exe "));
MultiByteToWideChar(65001, 0, string, -1, cmd_line + sizeof("cmd.exe ") - 1, wchars_required);
STARTUPINFOW si = {
.cb = sizeof(STARTUPINFOW),
.dwFlags = STARTF_USESTDHANDLES,
.hStdInput = GetStdHandle(STD_INPUT_HANDLE),
.hStdError = GetStdHandle(STD_ERROR_HANDLE),
.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
};
PROCESS_INFORMATION pi = {};
if (!CreateProcessW(NULL, cmd_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
goto error;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code;
if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {
goto error;
}
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
free(cmd_line);
return exit_code;
error:
free(cmd_line);
return -1;
}

View File

@ -1,58 +1,147 @@
#include <win.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <win.h>
#include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <threads.h>
#include <uchar.h>
enum str_type {
STR_R,
STR_W,
STR_A,
} typedef str_type;
enum str_flags {
STR_U = 1,
STR_X = 2,
STR_B = 4,
} typedef str_flags;
enum str_mode {
STR_BIN,
STR_TEXT,
} typedef str_mode;
// It's just mapped directly to HANDLE
struct FILE { struct FILE {
int unused; HANDLE handle;
char *name;
str_type type;
str_flags flags;
str_mode mode;
int buftype;
size_t bufsize;
char *buffer;
mbstate_t mbstate;
mtx_t lock;
FILE *prev;
FILE *next;
}; };
FILE *stdout; FILE *stdout;
FILE *stdin; FILE *stdin;
FILE *stderr; FILE *stderr;
int system(const char* string) { // Linked list because I'm based and you can't say I'm wrong
int wchars_required = MultiByteToWideChar(65001, 0, string, -1, NULL, 0); static FILE *file_list_last = NULL;
wchar_t* cmd_line = malloc(sizeof(L"cmd.exe ") + (wchars_required * sizeof(wchar_t)));
if (cmd_line == NULL) { static inline FILE *new_file(
goto error; HANDLE handle,
char *name,
str_type type,
str_flags flags,
int mode,
int buftype,
size_t bufsize,
char *buffer
) {
FILE *file = malloc(sizeof(FILE));
if(file == NULL) return NULL;
file->handle = handle;
file->name = name; // TODO: strdup this
file->type = type;
file->flags = flags;
file->mode = mode;
file->mbstate = (mbstate_t){0};
mtx_init(&file->lock, mtx_recursive);
if(file_list_last != NULL) {
file_list_last->next = file;
file->prev = file_list_last;
file->next = NULL;
} }
else {
memcpy(cmd_line, L"cmd.exe ", sizeof(L"cmd.exe ")); file_list_last = file;
MultiByteToWideChar(65001, 0, string, -1, cmd_line + sizeof("cmd.exe ") - 1, wchars_required); file->prev = NULL;
file->next = NULL;
STARTUPINFOW si = {
.cb = sizeof(STARTUPINFOW),
.dwFlags = STARTF_USESTDHANDLES,
.hStdInput = GetStdHandle(STD_INPUT_HANDLE),
.hStdError = GetStdHandle(STD_ERROR_HANDLE),
.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
};
PROCESS_INFORMATION pi = {};
if (!CreateProcessW(NULL, cmd_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
goto error;
} }
return file;
// Wait until child process exits. }
WaitForSingleObject(pi.hProcess, INFINITE);
static inline void dispose_file(FILE *file) {
DWORD exit_code; mtx_t lock = file->lock;
if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { mtx_lock(&lock);
goto error; // Only close the file if it's not a standard handle
} if(file->name) {
CloseHandle(file->handle);
// Close process and thread handles. //TODO: free(file->name);
CloseHandle(pi.hProcess); }
CloseHandle(pi.hThread); // TODO: flush streams
free(cmd_line); FILE *prev = file->prev;
return exit_code; FILE *next = file->next;
if(prev != NULL) prev->next = next;
error: if(next != NULL) next->prev = prev;
free(cmd_line); if(next == NULL) file_list_last = prev;
return -1; free(file);
mtx_unlock(&lock);
}
void _setup_io() {
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hstderr = GetStdHandle(STD_ERROR_HANDLE);
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
char *out_buf = calloc(BUFSIZ, sizeof(char));
char *err_buf = out_buf;
if(hstdout != hstderr) {
err_buf = calloc(BUFSIZ, sizeof(char));
}
stdout = new_file(hstdout, NULL, STR_W, 0, 0, _IOLBF, BUFSIZ, out_buf);
stderr = new_file(hstderr, NULL, STR_W, 0, 0, _IOLBF, BUFSIZ, err_buf);
stdin = new_file(hstdin, NULL, STR_R, 0, 0, _IONBF, 0, NULL);
}
int setvbuf(
FILE *restrict stream,
char *restrict buf,
int mode,
size_t size
) {
if(mode == _IONBF) {
stream->buftype = mode;
stream->buffer = NULL;
stream->bufsize = 0;
return 0;
}
if(mode != _IOFBF && mode != _IOLBF)
return 1;
if(buf == NULL && size != 0) {
buf = malloc(size);
}
if(size == 0) {
buf = NULL;
mode = _IONBF;
}
stream->buftype = mode;
stream->buffer = buf;
stream->bufsize = size;
return 0;
}
void setbuf(FILE *restrict stream, char *restrict buf) {
if(buf != NULL)
setvbuf(stream, buf, _IOFBF, BUFSIZ);
else
setvbuf(stream, buf, _IONBF, BUFSIZ);
} }

5
todo
View File

@ -1,4 +1,8 @@
general:
* Start writing documentation concerning various implementation defined
behaviours of the library.
locale.h: locale.h:
Make other locales actually work Make other locales actually work
@ -36,6 +40,7 @@ stdlib.h:
threads.h: threads.h:
Make _Thread_local work on windows Make _Thread_local work on windows
Verify the mtx_recursive goes ok. Also change win_stdio.c accordingly.
TODO: add todo items TODO: add todo items
tgmath.h: tgmath.h: