mirror of
https://gitlab.com/bztsrc/posix-uefi.git
synced 2024-12-28 06:55:08 +01:00
Added UTF-8 support
This commit is contained in:
parent
804d74b0a2
commit
acaf9f36ef
12 changed files with 416 additions and 269 deletions
116
README.md
116
README.md
|
@ -52,14 +52,26 @@ An example **helloworld.c** goes like this:
|
|||
```c
|
||||
#include <uefi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("Hello World!\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
By default it uses Clang + lld, and PE is generated without conversion. If `USE_GCC` is set, then the host native's GNU gcc + ld
|
||||
used to create a shared object and get converted into an .efi file.
|
||||
|
||||
If you comment out `USE_UTF8` in uefi.h, then all character representation will use `wchar_t`, and there will be no string
|
||||
conversion between your application and the UEFI interfaces. This also means you must use `L""` and `L''` literals everywhere:
|
||||
```c
|
||||
#include <uefi.h>
|
||||
|
||||
int main(int argc, wchar_t **argv)
|
||||
{
|
||||
printf(L"Hello World!\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
By default it uses Clang + lld, and PE is generated without conversion. If `USE_GCC` is set, then the host native's GNU gcc + ld
|
||||
used to create a shared object and get converted into an .efi file.
|
||||
|
||||
### Available Makefile Options
|
||||
|
||||
|
@ -97,10 +109,12 @@ for you, because simplicity was one of its main goals. It is the best to say thi
|
|||
rather than a POSIX compatible libc.
|
||||
|
||||
All strings in the UEFI environment are stored with 16 bits wide characters. The library provides `wchar_t` type for that,
|
||||
so for example your main() is NOT like `main(int argc, char **argv)`, but `main(int argc, wchar_t **argv)` instead. All
|
||||
the other string related libc functions (like strlen() for example) use this wide character type too. For this reason, you
|
||||
must specify your string literals with `L""` and characters with `L''`. Functions that supposed to handle characters in int
|
||||
type (like `getchar`, `putchar`), do not truncate to unsigned char, rather to wchar_t.
|
||||
and the `USE_UTF8` define to convert between `char` and `wchar_t` transparently. If you comment out `USE_UTF8`, then for
|
||||
example your main() will NOT be like `main(int argc, char **argv)`, but `main(int argc, wchar_t **argv)` instead. All
|
||||
the other string related libc functions (like strlen() for example) will use this wide character type too. For this reason,
|
||||
you must specify your string literals with `L""` and characters with `L''`. To handle both configurations, `char_t` type is
|
||||
defined, which is either `char` or `wchar_t`. Functions that supposed to handle characters in int type (like `getchar`,
|
||||
`putchar`), do not truncate to unsigned char, rather to wchar_t.
|
||||
|
||||
File types in dirent are limited to directories and files only (DT_DIR, DT_REG), but for stat in addition to S_IFDIR and
|
||||
S_IFREG, S_IFIFO also returned (for console streams: stdin, stdout, stderr).
|
||||
|
@ -116,7 +130,7 @@ List of Provided POSIX Functions
|
|||
|
||||
| Function | Description |
|
||||
|---------------|----------------------------------------------------------------------------|
|
||||
| opendir | as usual, but accepts wide char strings |
|
||||
| opendir | as usual, but might accept wide char strings |
|
||||
| readdir | as usual |
|
||||
| rewinddir | as usual |
|
||||
| closedir | as usual |
|
||||
|
@ -127,15 +141,16 @@ Because UEFI has no concept of device files nor of symlinks, dirent fields are l
|
|||
|
||||
| Function | Description |
|
||||
|---------------|----------------------------------------------------------------------------|
|
||||
| atoi | as usual, but accepts wide char strings and understands "0x" prefix |
|
||||
| atol | as usual, but accepts wide char strings and understands "0x" prefix |
|
||||
| strtol | as usual, but accepts wide char strings |
|
||||
| atoi | as usual, but might accept wide char strings and understands "0x" prefix |
|
||||
| atol | as usual, but might accept wide char strings and understands "0x" prefix |
|
||||
| strtol | as usual, but might accept wide char strings |
|
||||
| malloc | as usual |
|
||||
| calloc | as usual |
|
||||
| realloc | as usual (needs testing) |
|
||||
| free | as usual |
|
||||
| abort | as usual |
|
||||
| exit | as usual |
|
||||
| exit_bs | leave this entire UEFI bullshit behind (exit Boot Services) |
|
||||
| mbtowc | as usual (UTF-8 char to wchar_t) |
|
||||
| wctomb | as usual (wchar_t to UTF-8 char) |
|
||||
| mbstowcs | as usual (UTF-8 string to wchar_t string) |
|
||||
|
@ -146,12 +161,17 @@ Because UEFI has no concept of device files nor of symlinks, dirent fields are l
|
|||
| setenv | pretty UEFI specific |
|
||||
|
||||
```c
|
||||
uint8_t *getenv(wchar_t *name, uintn_t *len);
|
||||
int exit_bs()
|
||||
```
|
||||
Exit Boot Services. Returns 0 on success.
|
||||
|
||||
```c
|
||||
uint8_t *getenv(char_t *name, uintn_t *len);
|
||||
```
|
||||
Query the value of environment variable `name`. On success, `len` is set, and a malloc'd buffer returned. It is
|
||||
the caller's responsibility to free the buffer later. On error returns NULL.
|
||||
```c
|
||||
int setenv(wchar_t *name, uintn_t len, uint8_t *data);
|
||||
int setenv(char_t *name, uintn_t len, uint8_t *data);
|
||||
```
|
||||
Sets an environment variable by `name` with `data` of length `len`. On success returns 1, otherwise 0 on error.
|
||||
|
||||
|
@ -159,7 +179,7 @@ Sets an environment variable by `name` with `data` of length `len`. On success r
|
|||
|
||||
| Function | Description |
|
||||
|---------------|----------------------------------------------------------------------------|
|
||||
| fopen | as usual, but accepts wide char strings, also for mode |
|
||||
| fopen | as usual, but might accept wide char strings, also for mode |
|
||||
| fclose | as usual |
|
||||
| fflush | as usual |
|
||||
| fread | as usual, only real files accepted (no stdin) |
|
||||
|
@ -167,33 +187,27 @@ Sets an environment variable by `name` with `data` of length `len`. On success r
|
|||
| fseek | as usual, only real files accepted (no stdin, stdout, stderr) |
|
||||
| ftell | as usual, only real files accepted (no stdin, stdout, stderr) |
|
||||
| feof | as usual, only real files accepted (no stdin, stdout, stderr) |
|
||||
| fprintf | as usual, but accepts wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||
| printf | as usual, but accepts wide char strings, max BUFSIZ, stdout only |
|
||||
| sprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||
| vfprintf | as usual, but accepts wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||
| vprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||
| vsprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||
| snprintf | as usual, but accepts wide char strings |
|
||||
| vsnprintf | as usual, but accepts wide char strings |
|
||||
| getchar | as usual, waits for a key, blocking, stdin only (no redirects) |
|
||||
| fprintf | as usual, might be wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||
| printf | as usual, might be wide char strings, max BUFSIZ, stdout only |
|
||||
| sprintf | as usual, might be wide char strings, max BUFSIZ |
|
||||
| vfprintf | as usual, might be wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||
| vprintf | as usual, might be wide char strings, max BUFSIZ |
|
||||
| vsprintf | as usual, might be wide char strings, max BUFSIZ |
|
||||
| snprintf | as usual, might be wide char strings |
|
||||
| vsnprintf | as usual, might be wide char strings |
|
||||
| getchar | as usual, blocking, stdin only (no stream redirects), returns UNICODE |
|
||||
| getchar_ifany | non-blocking, returns 0 if there was no key press, UNICODE otherwise |
|
||||
| putchar | as usual, stdout only (no redirects) |
|
||||
| exit_bs | leave this entire UEFI bullshit behind (exit Boot Services) |
|
||||
| putchar | as usual, stdout only (no stream redirects) |
|
||||
|
||||
```c
|
||||
int exit_bs()
|
||||
```
|
||||
Exit Boot Services. Returns 0 on success.
|
||||
|
||||
File open modes: `L"r"` read, `L"w"` write, `L"a"` append. Because of UEFI peculiarities, `L"wd"` creates directory.
|
||||
File open modes: `"r"` read, `"w"` write, `"a"` append. Because of UEFI peculiarities, `"wd"` creates directory.
|
||||
|
||||
String formating is limited; only supports padding via number prefixes, `%d`, `%x`, `%X`, `%c`, `%s`, `%q` and
|
||||
`%p`. Because it operates on wchar_t, it also supports the non-standard `%C` (printing an UTF-8 character, needs
|
||||
char\*), `%S` (printing an UTF-8 string), `%Q` (printing an escaped UTF-8 string). These functions don't allocate
|
||||
memory, but in return the total length of the output string cannot be longer than BUFSIZ (8k if you haven't
|
||||
defined otherwise), except for the variants which have a maxlen argument. For convenience, `%D` requires
|
||||
`efi_physical_address_t` as argument, and it dumps memory, 16 bytes or one line at once. With the padding
|
||||
modifier you can dump more lines, for example `%5D` gives you 5 lines (80 dumped bytes).
|
||||
`%p`. When `USE_UTF8` is not defined, then formating operates on wchar_t, so it also supports the non-standard `%S`
|
||||
(printing an UTF-8 string), `%Q` (printing an escaped UTF-8 string). These functions don't allocate memory, but in
|
||||
return the total length of the output string cannot be longer than `BUFSIZ` (8k if you haven't defined otherwise),
|
||||
except for the variants which have a maxlen argument. For convenience, `%D` requires `efi_physical_address_t` as
|
||||
argument, and it dumps memory, 16 bytes or one line at once. With the padding modifier you can dump more lines, for
|
||||
example `%5D` gives you 5 lines (80 dumped bytes).
|
||||
|
||||
Special "device files" you can open:
|
||||
|
||||
|
@ -219,27 +233,27 @@ With disk devices, `fread` and `fwrite` arguments look like this: fread(ptr, buf
|
|||
| memrchr | as usual, works on bytes |
|
||||
| memmem | as usual, works on bytes |
|
||||
| memrmem | as usual, works on bytes |
|
||||
| strcpy | works on wide char strings |
|
||||
| strncpy | works on wide char strings |
|
||||
| strcat | works on wide char strings |
|
||||
| strncat | works on wide char strings |
|
||||
| strcmp | works on wide char strings |
|
||||
| strncmp | works on wide char strings |
|
||||
| strdup | works on wide char strings |
|
||||
| strchr | works on wide char strings |
|
||||
| strrchr | works on wide char strings |
|
||||
| strstr | works on wide char strings |
|
||||
| strtok | works on wide char strings |
|
||||
| strtok_r | works on wide char strings |
|
||||
| strlen | works on wide char strings |
|
||||
| strcpy | might work on wide char strings |
|
||||
| strncpy | might work on wide char strings |
|
||||
| strcat | might work on wide char strings |
|
||||
| strncat | might work on wide char strings |
|
||||
| strcmp | might work on wide char strings |
|
||||
| strncmp | might work on wide char strings |
|
||||
| strdup | might work on wide char strings |
|
||||
| strchr | might work on wide char strings |
|
||||
| strrchr | might work on wide char strings |
|
||||
| strstr | might work on wide char strings |
|
||||
| strtok | might work on wide char strings |
|
||||
| strtok_r | might work on wide char strings |
|
||||
| strlen | might work on wide char strings |
|
||||
|
||||
### sys/stat.h
|
||||
|
||||
| Function | Description |
|
||||
|---------------|----------------------------------------------------------------------------|
|
||||
| stat | as usual, but accepts wide char strings |
|
||||
| stat | as usual, but might accept wide char strings |
|
||||
| fstat | UEFI doesn't have fd, so it uses FILE\* |
|
||||
| mkdir | as usual, but accepts wide char strings, and mode unused |
|
||||
| mkdir | as usual, but might accept wide char strings, and mode unused |
|
||||
|
||||
Because UEFI has no concept of device major and minor number nor of inodes, struct stat's fields are limited.
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
/**
|
||||
* Classic Hello World example
|
||||
*/
|
||||
int main(int argc, wchar_t **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf(L"Hello World!\n");
|
||||
printf("Hello World!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#include <uefi.h>
|
||||
|
||||
/**
|
||||
* Print out arguments
|
||||
* Print out arguments. This source can be compiled with and without USE_UTF8
|
||||
*/
|
||||
int main(int argc, wchar_t **argv)
|
||||
int main(int argc, char_t **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(L"I got %d argument%s:\n", argc, argc > 1 ? L"s" : L"");
|
||||
printf(CL("I got %d argument%s:\n"), argc, argc > 1 ? CL("s") : CL(""));
|
||||
for(i = 0; i < argc; i++)
|
||||
printf(L" argv[%d] = '%s'\n", i, argv[i]);
|
||||
printf(CL(" argv[%d] = '%s'\n"), i, argv[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
/**
|
||||
* Dump memory at given address, should accept 0x prefixes from the command line
|
||||
*/
|
||||
int main(int argc, wchar_t **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
efi_physical_address_t address =
|
||||
(argc < 2 ? (efi_physical_address_t)IM : (efi_physical_address_t)atol(argv[1]));
|
||||
|
||||
printf(L"%4D", address);
|
||||
printf("%4D", address);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <uefi.h>
|
||||
|
||||
/* this is implemented by the application */
|
||||
extern int main(int argc, wchar_t **argv);
|
||||
extern int main(int argc, char_t **argv);
|
||||
|
||||
/* definitions for elf relocations */
|
||||
typedef uint64_t Elf64_Xword;
|
||||
|
@ -64,6 +64,9 @@ efi_system_table_t *ST = NULL;
|
|||
efi_boot_services_t *BS = NULL;
|
||||
efi_runtime_services_t *RT = NULL;
|
||||
efi_loaded_image_protocol_t *LIP = NULL;
|
||||
#if USE_UTF8
|
||||
char *__argvutf8 = NULL;
|
||||
#endif
|
||||
|
||||
/* we only need one .o file, so use inline Assembly here */
|
||||
void bootstrap()
|
||||
|
@ -153,10 +156,13 @@ int uefi_init (
|
|||
efi_shell_interface_protocol_t *shi = NULL;
|
||||
efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
int argc = 0;
|
||||
int argc = 0, i;
|
||||
wchar_t **argv = NULL;
|
||||
#if USE_UTF8
|
||||
int ret, j;
|
||||
char *s;
|
||||
#endif
|
||||
#ifndef __clang__
|
||||
int i;
|
||||
long relsz = 0, relent = 0;
|
||||
Elf64_Rel *rel = 0;
|
||||
uintptr_t *addr;
|
||||
|
@ -177,6 +183,8 @@ int uefi_init (
|
|||
relsz -= relent;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)i;
|
||||
#endif
|
||||
/* save EFI pointers and loaded image into globals */
|
||||
IM = image;
|
||||
|
@ -193,5 +201,32 @@ int uefi_init (
|
|||
if(!EFI_ERROR(status) && shi) { argc = shi->Argc; argv = shi->Argv; }
|
||||
}
|
||||
/* call main */
|
||||
#if USE_UTF8
|
||||
if(argc && argv) {
|
||||
ret = (argc + 1) * (sizeof(uintptr_t) + 1);
|
||||
for(i = 0; i < argc; i++)
|
||||
for(j = 0; argv[i] && argv[i][j]; j++)
|
||||
ret += argv[i][j] < 0x80 ? 1 : (argv[i][j] < 0x800 ? 2 : 3);
|
||||
status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, ret, (void **)&__argvutf8);
|
||||
if(EFI_ERROR(status) || !__argvutf8) { argc = 0; __argvutf8 = NULL; }
|
||||
else {
|
||||
s = __argvutf8 + argc * sizeof(uintptr_t);
|
||||
*((uintptr_t*)s) = (uintptr_t)0; s += sizeof(uintptr_t);
|
||||
for(i = 0; i < argc; i++) {
|
||||
*((uintptr_t*)(__argvutf8 + i * sizeof(uintptr_t))) = (uintptr_t)s;
|
||||
for(j = 0; argv[i] && argv[i][j]; j++) {
|
||||
if(argv[i][j]<0x80) { *s++ = argv[i][j]; } else
|
||||
if(argv[i][j]<0x800) { *s++ = ((argv[i][j]>>6)&0x1F)|0xC0; *s++ = (argv[i][j]&0x3F)|0x80; } else
|
||||
{ *s++ = ((argv[i][j]>>12)&0x0F)|0xE0; *s++ = ((argv[i][j]>>6)&0x3F)|0x80; *s++ = (argv[i][j]&0x3F)|0x80; }
|
||||
}
|
||||
*s++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = main(argc, (char**)__argvutf8);
|
||||
if(__argvutf8) BS->FreePool(__argvutf8);
|
||||
return ret;
|
||||
#else
|
||||
return main(argc, argv);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <uefi.h>
|
||||
|
||||
/* this is implemented by the application */
|
||||
extern int main(int argc, wchar_t **argv);
|
||||
extern int main(int argc, char_t **argv);
|
||||
|
||||
/* definitions for elf relocations */
|
||||
typedef uint64_t Elf64_Xword;
|
||||
|
@ -64,6 +64,9 @@ efi_system_table_t *ST = NULL;
|
|||
efi_boot_services_t *BS = NULL;
|
||||
efi_runtime_services_t *RT = NULL;
|
||||
efi_loaded_image_protocol_t *LIP = NULL;
|
||||
#if USE_UTF8
|
||||
char *__argvutf8 = NULL;
|
||||
#endif
|
||||
|
||||
/* we only need one .o file, so use inline Assembly here */
|
||||
void bootstrap()
|
||||
|
@ -147,10 +150,13 @@ int uefi_init (
|
|||
efi_shell_interface_protocol_t *shi = NULL;
|
||||
efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
int argc = 0;
|
||||
int argc = 0, i;
|
||||
wchar_t **argv = NULL;
|
||||
#if USE_UTF8
|
||||
int ret, j;
|
||||
char *s;
|
||||
#endif
|
||||
#ifndef __clang__
|
||||
int i;
|
||||
long relsz = 0, relent = 0;
|
||||
Elf64_Rel *rel = 0;
|
||||
uintptr_t *addr;
|
||||
|
@ -171,6 +177,8 @@ int uefi_init (
|
|||
relsz -= relent;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)i;
|
||||
#endif
|
||||
/* save EFI pointers and loaded image into globals */
|
||||
IM = image;
|
||||
|
@ -187,5 +195,32 @@ int uefi_init (
|
|||
if(!EFI_ERROR(status) && shi) { argc = shi->Argc; argv = shi->Argv; }
|
||||
}
|
||||
/* call main */
|
||||
#if USE_UTF8
|
||||
if(argc && argv) {
|
||||
ret = (argc + 1) * (sizeof(uintptr_t) + 1);
|
||||
for(i = 0; i < argc; i++)
|
||||
for(j = 0; argv[i] && argv[i][j]; j++)
|
||||
ret += argv[i][j] < 0x80 ? 1 : (argv[i][j] < 0x800 ? 2 : 3);
|
||||
status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, ret, (void **)&__argvutf8);
|
||||
if(EFI_ERROR(status) || !__argvutf8) { argc = 0; __argvutf8 = NULL; }
|
||||
else {
|
||||
s = __argvutf8 + argc * sizeof(uintptr_t);
|
||||
*((uintptr_t*)s) = (uintptr_t)0; s += sizeof(uintptr_t);
|
||||
for(i = 0; i < argc; i++) {
|
||||
*((uintptr_t*)(__argvutf8 + i * sizeof(uintptr_t))) = (uintptr_t)s;
|
||||
for(j = 0; argv[i] && argv[i][j]; j++) {
|
||||
if(argv[i][j]<0x80) { *s++ = argv[i][j]; } else
|
||||
if(argv[i][j]<0x800) { *s++ = ((argv[i][j]>>6)&0x1F)|0xC0; *s++ = (argv[i][j]&0x3F)|0x80; } else
|
||||
{ *s++ = ((argv[i][j]>>12)&0x0F)|0xE0; *s++ = ((argv[i][j]>>6)&0x3F)|0x80; *s++ = (argv[i][j]&0x3F)|0x80; }
|
||||
}
|
||||
*s++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = main(argc, (char**)__argvutf8);
|
||||
if(__argvutf8) BS->FreePool(__argvutf8);
|
||||
return ret;
|
||||
#else
|
||||
return main(argc, argv);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
extern void __stdio_seterrno(efi_status_t status);
|
||||
struct dirent __dirent;
|
||||
|
||||
DIR *opendir (const wchar_t *__name)
|
||||
DIR *opendir (const char_t *__name)
|
||||
{
|
||||
DIR *dp = (DIR*)fopen(__name, L"rd");
|
||||
DIR *dp = (DIR*)fopen(__name, CL("rd"));
|
||||
rewinddir(dp);
|
||||
return dp;
|
||||
}
|
||||
|
@ -53,8 +53,12 @@ struct dirent *readdir (DIR *__dirp)
|
|||
return NULL;
|
||||
}
|
||||
__dirent.d_type = info.Attribute & EFI_FILE_DIRECTORY ? DT_DIR : DT_REG;
|
||||
#if USE_UTF8
|
||||
__dirent.d_reclen = wcstombs(__dirent.d_name, info.FileName, FILENAME_MAX - 1);
|
||||
#else
|
||||
__dirent.d_reclen = strlen(info.FileName);
|
||||
strcpy(__dirent.d_name, info.FileName);
|
||||
strncpy(__dirent.d_name, info.FileName, FILENAME_MAX - 1);
|
||||
#endif
|
||||
return &__dirent;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ int fstat (FILE *__f, struct stat *__buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int stat (const wchar_t *__file, struct stat *__buf)
|
||||
int stat (const char_t *__file, struct stat *__buf)
|
||||
{
|
||||
int ret;
|
||||
FILE *f;
|
||||
|
@ -79,7 +79,7 @@ int stat (const wchar_t *__file, struct stat *__buf)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
f = fopen(__file, L"*");
|
||||
f = fopen(__file, CL("*"));
|
||||
if(!f) {
|
||||
memset(__buf, 0, sizeof(struct stat));
|
||||
return -1;
|
||||
|
@ -89,7 +89,7 @@ int stat (const wchar_t *__file, struct stat *__buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
extern int mkdir (const wchar_t *__path, mode_t __mode)
|
||||
extern int mkdir (const char_t *__path, mode_t __mode)
|
||||
{
|
||||
FILE *f;
|
||||
(void)__mode;
|
||||
|
@ -97,7 +97,7 @@ extern int mkdir (const wchar_t *__path, mode_t __mode)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
f = fopen(__path, L"wd");
|
||||
f = fopen(__path, CL("wd"));
|
||||
if(!f) {
|
||||
return -1;
|
||||
}
|
||||
|
|
223
uefi/stdio.c
223
uefi/stdio.c
|
@ -35,6 +35,19 @@ static efi_serial_io_protocol_t *__ser = NULL;
|
|||
static efi_block_io_t **__blk_devs = NULL;
|
||||
static uintn_t __blk_ndevs = 0;
|
||||
|
||||
void __stdio_cleanup()
|
||||
{
|
||||
#if USE_UTF8
|
||||
if(__argvutf8)
|
||||
free(__argvutf8);
|
||||
#endif
|
||||
if(__blk_devs) {
|
||||
free(__blk_devs);
|
||||
__blk_devs = NULL;
|
||||
__blk_ndevs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void __stdio_seterrno(efi_status_t status)
|
||||
{
|
||||
switch((int)(status & 0xffff)) {
|
||||
|
@ -79,13 +92,13 @@ int fflush (FILE *__stream)
|
|||
return !EFI_ERROR(status);
|
||||
}
|
||||
|
||||
int __remove (const wchar_t *__filename, int isdir)
|
||||
int __remove (const char_t *__filename, int isdir)
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_guid_t infGuid = EFI_FILE_INFO_GUID;
|
||||
efi_file_info_t info;
|
||||
uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t), i;
|
||||
FILE *f = fopen(__filename, L"r");
|
||||
FILE *f = fopen(__filename, CL("r"));
|
||||
if(f == stdin || f == stdout || f == stderr || (__ser && f == (FILE*)__ser)) {
|
||||
errno = EBADF;
|
||||
return 1;
|
||||
|
@ -118,12 +131,12 @@ err: __stdio_seterrno(status);
|
|||
return 0;
|
||||
}
|
||||
|
||||
int remove (const wchar_t *__filename)
|
||||
int remove (const char_t *__filename)
|
||||
{
|
||||
return __remove(__filename, -1);
|
||||
}
|
||||
|
||||
FILE *fopen (const wchar_t *__filename, const wchar_t *__modes)
|
||||
FILE *fopen (const char_t *__filename, const char_t *__modes)
|
||||
{
|
||||
FILE *ret;
|
||||
efi_status_t status;
|
||||
|
@ -132,25 +145,27 @@ FILE *fopen (const wchar_t *__filename, const wchar_t *__modes)
|
|||
efi_guid_t infGuid = EFI_FILE_INFO_GUID;
|
||||
efi_file_info_t info;
|
||||
uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t), par, i;
|
||||
|
||||
#if USE_UTF8
|
||||
wchar_t wcname[BUFSIZ];
|
||||
#endif
|
||||
if(!__filename || !*__filename || !__modes || !*__modes) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
/* fake some device names. UEFI has no concept of device files */
|
||||
if(!strcmp(__filename, L"/dev/stdin")) {
|
||||
if(__modes[0] == L'w' || __modes[0] == L'a') { errno = EPERM; return NULL; }
|
||||
if(!strcmp(__filename, CL("/dev/stdin"))) {
|
||||
if(__modes[0] == CL('w') || __modes[0] == CL('a')) { errno = EPERM; return NULL; }
|
||||
return stdin;
|
||||
}
|
||||
if(!strcmp(__filename, L"/dev/stdout")) {
|
||||
if(__modes[0] == L'r') { errno = EPERM; return NULL; }
|
||||
if(!strcmp(__filename, CL("/dev/stdout"))) {
|
||||
if(__modes[0] == CL('r')) { errno = EPERM; return NULL; }
|
||||
return stdout;
|
||||
}
|
||||
if(!strcmp(__filename, L"/dev/stderr")) {
|
||||
if(__modes[0] == L'r') { errno = EPERM; return NULL; }
|
||||
if(!strcmp(__filename, CL("/dev/stderr"))) {
|
||||
if(__modes[0] == CL('r')) { errno = EPERM; return NULL; }
|
||||
return stderr;
|
||||
}
|
||||
if(!memcmp(__filename, L"/dev/serial", 22)) {
|
||||
if(!memcmp(__filename, CL("/dev/serial"), 11 * sizeof(char_t))) {
|
||||
par = atol(__filename + 11);
|
||||
if(!__ser) {
|
||||
efi_guid_t serGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
|
||||
|
@ -160,7 +175,7 @@ FILE *fopen (const wchar_t *__filename, const wchar_t *__modes)
|
|||
__ser->SetAttributes(__ser, par > 9600 ? par : 115200, 0, 1000, NoParity, 8, OneStopBit);
|
||||
return (FILE*)__ser;
|
||||
}
|
||||
if(!memcmp(__filename, L"/dev/disk", 18)) {
|
||||
if(!memcmp(__filename, CL("/dev/disk"), 9 * sizeof(char_t))) {
|
||||
par = atol(__filename + 9);
|
||||
if(!__blk_ndevs) {
|
||||
efi_guid_t bioGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
|
||||
|
@ -202,22 +217,27 @@ FILE *fopen (const wchar_t *__filename, const wchar_t *__modes)
|
|||
errno = 0;
|
||||
ret = (FILE*)malloc(sizeof(FILE));
|
||||
if(!ret) return NULL;
|
||||
#if USE_UTF8
|
||||
mbstowcs((wchar_t*)&wcname, __filename, BUFSIZ - 1);
|
||||
status = __root_dir->Open(__root_dir, &ret, (wchar_t*)&wcname,
|
||||
#else
|
||||
status = __root_dir->Open(__root_dir, &ret, (wchar_t*)__filename,
|
||||
__modes[0] == L'w' ? (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE) : EFI_FILE_MODE_READ,
|
||||
__modes[1] == L'd' ? EFI_FILE_DIRECTORY : 0);
|
||||
#endif
|
||||
__modes[0] == CL('w') ? (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE) : EFI_FILE_MODE_READ,
|
||||
__modes[1] == CL('d') ? EFI_FILE_DIRECTORY : 0);
|
||||
if(EFI_ERROR(status)) {
|
||||
err: __stdio_seterrno(status);
|
||||
free(ret); ret = NULL;
|
||||
}
|
||||
status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
|
||||
if(EFI_ERROR(status)) goto err;
|
||||
if(__modes[1] == L'd' && !(info.Attribute & EFI_FILE_DIRECTORY)) {
|
||||
if(__modes[1] == CL('d') && !(info.Attribute & EFI_FILE_DIRECTORY)) {
|
||||
free(ret); errno = ENOTDIR; return NULL;
|
||||
}
|
||||
if(__modes[1] != L'd' && (info.Attribute & EFI_FILE_DIRECTORY)) {
|
||||
if(__modes[1] != CL('d') && (info.Attribute & EFI_FILE_DIRECTORY)) {
|
||||
free(ret); errno = EISDIR; return NULL;
|
||||
}
|
||||
if(__modes[0] == L'a') fseek(ret, 0, SEEK_END);
|
||||
if(__modes[0] == CL('a')) fseek(ret, 0, SEEK_END);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -377,15 +397,15 @@ err: __stdio_seterrno(status);
|
|||
return info.FileSize == off;
|
||||
}
|
||||
|
||||
int vsnprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, __builtin_va_list args)
|
||||
int vsnprintf(char_t *dst, size_t maxlen, const char_t *fmt, __builtin_va_list args)
|
||||
{
|
||||
#define needsescape(a) (a==L'\"' || a==L'\\' || a==L'\a' || a==L'\b' || a==L'\033' || a=='\f' || \
|
||||
a==L'\r' || a==L'\n' || a==L'\t' || a=='\v')
|
||||
#define needsescape(a) (a==CL('\"') || a==CL('\\') || a==CL('\a') || a==CL('\b') || a==CL('\033') || a==CL('\f') || \
|
||||
a==CL('\r') || a==CL('\n') || a==CL('\t') || a==CL('\v'))
|
||||
efi_physical_address_t m;
|
||||
uint8_t *mem;
|
||||
int64_t arg;
|
||||
int len, sign, i, j;
|
||||
wchar_t *p, *orig=dst, *end = dst + maxlen - 1, tmpstr[19], pad=' ', n;
|
||||
char_t *p, *orig=dst, *end = dst + maxlen - 1, tmpstr[19], pad=CL(' '), n;
|
||||
char *c;
|
||||
|
||||
if(dst==NULL || fmt==NULL)
|
||||
|
@ -393,37 +413,30 @@ int vsnprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, __builtin_va_list
|
|||
|
||||
arg = 0;
|
||||
while(*fmt && dst < end) {
|
||||
if(*fmt==L'%') {
|
||||
if(*fmt==CL('%')) {
|
||||
fmt++;
|
||||
if(*fmt==L'%') goto put;
|
||||
if(*fmt==CL('%')) goto put;
|
||||
len=0;
|
||||
if(*fmt==L'0') pad=L'0';
|
||||
while(*fmt>=L'0' && *fmt<=L'9') {
|
||||
if(*fmt==CL('0')) pad=CL('0');
|
||||
while(*fmt>=CL('0') && *fmt<=CL('9')) {
|
||||
len *= 10;
|
||||
len += *fmt-L'0';
|
||||
len += *fmt-CL('0');
|
||||
fmt++;
|
||||
}
|
||||
if(*fmt==L'l') fmt++;
|
||||
if(*fmt==L'c') {
|
||||
if(*fmt==CL('l')) fmt++;
|
||||
if(*fmt==CL('c')) {
|
||||
arg = __builtin_va_arg(args, int);
|
||||
#if USE_UTF8
|
||||
if(arg<0x80) { *dst++ = arg; } else
|
||||
if(arg<0x800) { *dst++ = ((arg>>6)&0x1F)|0xC0; *dst++ = (arg&0x3F)|0x80; } else
|
||||
{ *dst++ = ((arg>>12)&0x0F)|0xE0; *dst++ = ((arg>>6)&0x3F)|0x80; *dst++ = (arg&0x3F)|0x80; }
|
||||
#else
|
||||
*dst++ = (wchar_t)(arg & 0xffff);
|
||||
#endif
|
||||
fmt++;
|
||||
continue;
|
||||
} else
|
||||
if(*fmt==L'C') {
|
||||
c = __builtin_va_arg(args, char*);
|
||||
arg = *c;
|
||||
if((*c & 128) != 0) {
|
||||
if((*c & 32) == 0 ) { arg = ((*c & 0x1F)<<6)|(*(c+1) & 0x3F); } else
|
||||
if((*c & 16) == 0 ) { arg = ((*c & 0xF)<<12)|((*(c+1) & 0x3F)<<6)|(*(c+2) & 0x3F); } else
|
||||
if((*c & 8) == 0 ) { arg = ((*c & 0x7)<<18)|((*(c+1) & 0x3F)<<12)|((*(c+2) & 0x3F)<<6)|(*(c+3) & 0x3F); }
|
||||
else arg = L'?';
|
||||
}
|
||||
*dst++ = (wchar_t)(arg & 0xffff);
|
||||
fmt++;
|
||||
continue;
|
||||
} else
|
||||
if(*fmt==L'd') {
|
||||
if(*fmt==CL('d')) {
|
||||
arg = __builtin_va_arg(args, int);
|
||||
sign=0;
|
||||
if((int)arg<0) {
|
||||
|
@ -436,11 +449,11 @@ int vsnprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, __builtin_va_list
|
|||
i=18;
|
||||
tmpstr[i]=0;
|
||||
do {
|
||||
tmpstr[--i]=L'0'+(arg%10);
|
||||
tmpstr[--i]=CL('0')+(arg%10);
|
||||
arg/=10;
|
||||
} while(arg!=0 && i>0);
|
||||
if(sign) {
|
||||
tmpstr[--i]=L'-';
|
||||
tmpstr[--i]=CL('-');
|
||||
}
|
||||
if(len>0 && len<18) {
|
||||
while(i>18-len) {
|
||||
|
@ -450,53 +463,53 @@ int vsnprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, __builtin_va_list
|
|||
p=&tmpstr[i];
|
||||
goto copystring;
|
||||
} else
|
||||
if(*fmt==L'p' || *fmt==L'P') {
|
||||
if(*fmt==CL('p')) {
|
||||
arg = __builtin_va_arg(args, uint64_t);
|
||||
len = 16; pad = L'0'; goto hex;
|
||||
len = 16; pad = CL('0'); goto hex;
|
||||
} else
|
||||
if(*fmt==L'x' || *fmt==L'X' || *fmt==L'p') {
|
||||
if(*fmt==CL('x') || *fmt==CL('X')) {
|
||||
arg = __builtin_va_arg(args, long int);
|
||||
if(*fmt==L'p') { len = 16; pad = L'0'; }
|
||||
hex: i=16;
|
||||
tmpstr[i]=0;
|
||||
do {
|
||||
n=arg & 0xf;
|
||||
/* 0-9 => '0'-'9', 10-15 => 'A'-'F' */
|
||||
tmpstr[--i]=n+(n>9?(*fmt==L'X'?0x37:0x57):0x30);
|
||||
tmpstr[--i]=n+(n>9?(*fmt==CL('X')?0x37:0x57):0x30);
|
||||
arg>>=4;
|
||||
} while(arg!=0 && i>0);
|
||||
/* padding, only leading zeros */
|
||||
if(len>0 && len<=16) {
|
||||
while(i>16-len) {
|
||||
tmpstr[--i]=L'0';
|
||||
tmpstr[--i]=CL('0');
|
||||
}
|
||||
}
|
||||
p=&tmpstr[i];
|
||||
goto copystring;
|
||||
} else
|
||||
if(*fmt==L's' || *fmt==L'q') {
|
||||
p = __builtin_va_arg(args, wchar_t*);
|
||||
if(*fmt==CL('s') || *fmt==CL('q')) {
|
||||
p = __builtin_va_arg(args, char_t*);
|
||||
copystring: if(p==NULL) {
|
||||
p=L"(null)";
|
||||
p=CL("(null)");
|
||||
}
|
||||
while(*p && dst + 2 < end) {
|
||||
if(*fmt==L'q' && needsescape(*p)) {
|
||||
*dst++ = L'\\';
|
||||
if(*fmt==CL('q') && needsescape(*p)) {
|
||||
*dst++ = CL('\\');
|
||||
switch(*p) {
|
||||
case L'\a': *dst++ = L'a'; break;
|
||||
case L'\b': *dst++ = L'b'; break;
|
||||
case L'\e': *dst++ = L'e'; break;
|
||||
case L'\f': *dst++ = L'f'; break;
|
||||
case L'\n': *dst++ = L'n'; break;
|
||||
case L'\r': *dst++ = L'r'; break;
|
||||
case L'\t': *dst++ = L't'; break;
|
||||
case L'\v': *dst++ = L'v'; break;
|
||||
case CL('\a'): *dst++ = CL('a'); break;
|
||||
case CL('\b'): *dst++ = CL('b'); break;
|
||||
case CL('\e'): *dst++ = CL('e'); break;
|
||||
case CL('\f'): *dst++ = CL('f'); break;
|
||||
case CL('\n'): *dst++ = CL('n'); break;
|
||||
case CL('\r'): *dst++ = CL('r'); break;
|
||||
case CL('\t'): *dst++ = CL('t'); break;
|
||||
case CL('\v'): *dst++ = CL('v'); break;
|
||||
default: *dst++ = *p++; break;
|
||||
}
|
||||
} else
|
||||
*dst++ = *p++;
|
||||
}
|
||||
} else
|
||||
#if !defined(USE_UTF8) || !USE_UTF8
|
||||
if(*fmt==L'S' || *fmt==L'Q') {
|
||||
c = __builtin_va_arg(args, char*);
|
||||
if(c==NULL) goto copystring;
|
||||
|
@ -537,33 +550,34 @@ copystring: if(p==NULL) {
|
|||
}
|
||||
}
|
||||
} else
|
||||
if(*fmt==L'D') {
|
||||
#endif
|
||||
if(*fmt==CL('D')) {
|
||||
m = __builtin_va_arg(args, efi_physical_address_t);
|
||||
for(j = 0; j < (len < 1 ? 1 : (len > 16 ? 16 : len)); j++) {
|
||||
for(i = 44; i >= 0; i -= 4) {
|
||||
n = (m >> i) & 15; *dst++ = n + (n>9?0x37:0x30);
|
||||
if(dst >= end) goto zro;
|
||||
}
|
||||
*dst++ = L':'; if(dst >= end) goto zro;
|
||||
*dst++ = L' '; if(dst >= end) goto zro;
|
||||
*dst++ = CL(':'); if(dst >= end) goto zro;
|
||||
*dst++ = CL(' '); if(dst >= end) goto zro;
|
||||
mem = (uint8_t*)m;
|
||||
for(i = 0; i < 16; i++) {
|
||||
n = (mem[i] >> 4) & 15; *dst++ = n + (n>9?0x37:0x30); if(dst >= end) goto zro;
|
||||
n = mem[i] & 15; *dst++ = n + (n>9?0x37:0x30); if(dst >= end) goto zro;
|
||||
*dst++ = L' ';if(dst >= end) goto zro;
|
||||
*dst++ = CL(' ');if(dst >= end) goto zro;
|
||||
}
|
||||
*dst++ = L' '; if(dst >= end) goto zro;
|
||||
*dst++ = CL(' '); if(dst >= end) goto zro;
|
||||
for(i = 0; i < 16; i++) {
|
||||
*dst++ = (mem[i] < 32 || mem[i] >= 127 ? L'.' : mem[i]);
|
||||
*dst++ = (mem[i] < 32 || mem[i] >= 127 ? CL('.') : mem[i]);
|
||||
if(dst >= end) goto zro;
|
||||
}
|
||||
*dst++ = L'\r'; if(dst >= end) goto zro;
|
||||
*dst++ = L'\n'; if(dst >= end) goto zro;
|
||||
*dst++ = CL('\r'); if(dst >= end) goto zro;
|
||||
*dst++ = CL('\n'); if(dst >= end) goto zro;
|
||||
m += 16;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
put: if(*fmt == L'\n') *dst++ = L'\r';
|
||||
put: if(*fmt == CL('\n') && (orig == dst || *(dst - 1) != CL('\r'))) *dst++ = CL('\r');
|
||||
*dst++ = *fmt;
|
||||
}
|
||||
fmt++;
|
||||
|
@ -573,48 +587,59 @@ zro:*dst=0;
|
|||
#undef needsescape
|
||||
}
|
||||
|
||||
int vsprintf(wchar_t *dst, const wchar_t *fmt, __builtin_va_list args)
|
||||
int vsprintf(char_t *dst, const char_t *fmt, __builtin_va_list args)
|
||||
{
|
||||
return vsnprintf(dst, BUFSIZ, fmt, args);
|
||||
}
|
||||
|
||||
int sprintf(wchar_t *dst, const wchar_t* fmt, ...)
|
||||
int sprintf(char_t *dst, const char_t* fmt, ...)
|
||||
{
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, fmt);
|
||||
return vsnprintf(dst, BUFSIZ, fmt, args);
|
||||
}
|
||||
|
||||
int snprintf(wchar_t *dst, size_t maxlen, const wchar_t* fmt, ...)
|
||||
int snprintf(char_t *dst, size_t maxlen, const char_t* fmt, ...)
|
||||
{
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, fmt);
|
||||
return vsnprintf(dst, maxlen, fmt, args);
|
||||
}
|
||||
|
||||
int vprintf(const wchar_t* fmt, __builtin_va_list args)
|
||||
int vprintf(const char_t* fmt, __builtin_va_list args)
|
||||
{
|
||||
wchar_t dst[BUFSIZ];
|
||||
int ret;
|
||||
wchar_t dst[BUFSIZ];
|
||||
#if USE_UTF8
|
||||
char_t tmp[BUFSIZ];
|
||||
ret = vsnprintf(tmp, sizeof(tmp), fmt, args);
|
||||
mbstowcs(dst, tmp, BUFSIZ - 1);
|
||||
#else
|
||||
ret = vsnprintf(dst, sizeof(dst), fmt, args);
|
||||
#endif
|
||||
ST->ConOut->OutputString(ST->ConOut, (wchar_t *)&dst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int printf(const wchar_t* fmt, ...)
|
||||
int printf(const char_t* fmt, ...)
|
||||
{
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, fmt);
|
||||
return vprintf(fmt, args);
|
||||
}
|
||||
|
||||
int vfprintf (FILE *__stream, const wchar_t *__format, __builtin_va_list args)
|
||||
int vfprintf (FILE *__stream, const char_t *__format, __builtin_va_list args)
|
||||
{
|
||||
wchar_t dst[BUFSIZ];
|
||||
char_t tmp[BUFSIZ];
|
||||
uintn_t ret, bs, i;
|
||||
if(__stream == stdin) return 0;
|
||||
#if USE_UTF8
|
||||
ret = vsnprintf(tmp, sizeof(tmp), __format, args);
|
||||
ret = mbstowcs(dst, tmp, BUFSIZ - 1);
|
||||
#else
|
||||
ret = vsnprintf(dst, sizeof(dst), __format, args);
|
||||
if(ret < 1) return 0;
|
||||
#endif
|
||||
if(ret < 1 || __stream == stdin) return 0;
|
||||
for(i = 0; i < __blk_ndevs; i++)
|
||||
if(__stream == (FILE*)__blk_devs[i]) {
|
||||
errno = EBADF;
|
||||
|
@ -624,14 +649,21 @@ int vfprintf (FILE *__stream, const wchar_t *__format, __builtin_va_list args)
|
|||
ST->ConOut->OutputString(ST->ConOut, (wchar_t*)&dst);
|
||||
else if(__stream == stderr)
|
||||
ST->StdErr->OutputString(ST->StdErr, (wchar_t*)&dst);
|
||||
else if(__ser && __stream == (FILE*)__ser)
|
||||
__ser->Write(__ser, &ret, (void*)&dst);
|
||||
else
|
||||
else if(__ser && __stream == (FILE*)__ser) {
|
||||
#if !defined(USE_UTF8) || !USE_UTF8
|
||||
wcstombs((char*)&tmp, dst, BUFSIZ - 1);
|
||||
#endif
|
||||
__ser->Write(__ser, &ret, (void*)&tmp);
|
||||
} else
|
||||
#if USE_UTF8
|
||||
__stream->Write(__stream, &ret, (void*)&tmp);
|
||||
#else
|
||||
__stream->Write(__stream, &ret, (void*)&dst);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fprintf (FILE *__stream, const wchar_t *__format, ...)
|
||||
int fprintf (FILE *__stream, const char_t *__format, ...)
|
||||
{
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, __format);
|
||||
|
@ -665,22 +697,3 @@ int putchar (int __c)
|
|||
ST->ConOut->OutputString(ST->ConOut, (__c == L'\n' ? (wchar_t*)L"\r\n" : (wchar_t*)&tmp));
|
||||
return (int)tmp[0];
|
||||
}
|
||||
|
||||
int exit_bs()
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_memory_descriptor_t *memory_map = NULL;
|
||||
uintn_t cnt = 3, memory_map_size=0, map_key=0, desc_size=0, i;
|
||||
if(__blk_devs) {
|
||||
free(__blk_devs);
|
||||
__blk_devs = NULL;
|
||||
__blk_ndevs = 0;
|
||||
}
|
||||
while(cnt--) {
|
||||
status = BS->GetMemoryMap(&memory_map_size, memory_map, &map_key, &desc_size, NULL);
|
||||
if (status!=EFI_BUFFER_TOO_SMALL) break;
|
||||
status = BS->ExitBootServices(IM, map_key);
|
||||
if(!EFI_ERROR(status)) return 0;
|
||||
}
|
||||
return (int)(status & 0xffff);
|
||||
}
|
||||
|
|
|
@ -32,43 +32,44 @@
|
|||
|
||||
int errno = 0;
|
||||
static uint64_t __srand_seed = 6364136223846793005ULL;
|
||||
extern void __stdio_cleanup();
|
||||
|
||||
int atoi(const wchar_t *s)
|
||||
int atoi(const char_t *s)
|
||||
{
|
||||
return (int)atol(s);
|
||||
}
|
||||
|
||||
int64_t atol(const wchar_t *s)
|
||||
int64_t atol(const char_t *s)
|
||||
{
|
||||
int64_t sign = 1;
|
||||
if(!s || !*s) return 0;
|
||||
if(*s == L'-') { sign = -1; s++; }
|
||||
if(s[0] == L'0') {
|
||||
if(s[1] == L'x')
|
||||
return strtol(s + 2, NULL, 16);
|
||||
if(s[1] >= L'0' && s[1] <= L'7')
|
||||
return strtol(s, NULL, 8);
|
||||
if(*s == CL('-')) { sign = -1; s++; }
|
||||
if(s[0] == CL('0')) {
|
||||
if(s[1] == CL('x'))
|
||||
return strtol(s + 2, NULL, 16) * sign;
|
||||
if(s[1] >= CL('0') && s[1] <= CL('7'))
|
||||
return strtol(s, NULL, 8) * sign;
|
||||
}
|
||||
return strtol(s, NULL, 10) * sign;
|
||||
}
|
||||
|
||||
int64_t strtol (const wchar_t *s, wchar_t **__endptr, int __base)
|
||||
int64_t strtol (const char_t *s, char_t **__endptr, int __base)
|
||||
{
|
||||
int64_t v=0, sign = 1;
|
||||
if(!s || !*s) return 0;
|
||||
if(*s == L'-') { sign = -1; s++; }
|
||||
while(!(*s < L'0' || (__base < 10 && *s >= __base + L'0') || (__base >= 10 && ((*s > L'9' && *s < L'A') ||
|
||||
(*s > L'F' && *s < L'a') || *s > L'f')))) {
|
||||
if(*s == CL('-')) { sign = -1; s++; }
|
||||
while(!(*s < CL('0') || (__base < 10 && *s >= __base + CL('0')) || (__base >= 10 && ((*s > CL('9') && *s < CL('A')) ||
|
||||
(*s > CL('F') && *s < CL('a')) || *s > CL('f'))))) {
|
||||
v *= __base;
|
||||
if(*s >= L'0' && *s <= (__base < 10 ? __base + L'0' : L'9'))
|
||||
v += (*s)-L'0';
|
||||
else if(__base == 16 && *s >= L'a' && *s <= L'f')
|
||||
v += (*s)-L'a'+10;
|
||||
else if(__base == 16 && *s >= L'A' && *s <= L'F')
|
||||
v += (*s)-L'A'+10;
|
||||
if(*s >= CL('0') && *s <= (__base < 10 ? __base + CL('0') : CL('9')))
|
||||
v += (*s)-CL('0');
|
||||
else if(__base == 16 && *s >= CL('a') && *s <= CL('f'))
|
||||
v += (*s)-CL('a')+10;
|
||||
else if(__base == 16 && *s >= CL('A') && *s <= CL('F'))
|
||||
v += (*s)-CL('A')+10;
|
||||
s++;
|
||||
};
|
||||
if(__endptr) *__endptr = (wchar_t*)s;
|
||||
if(__endptr) *__endptr = (char_t*)s;
|
||||
return v * sign;
|
||||
}
|
||||
|
||||
|
@ -112,14 +113,31 @@ void free (void *__ptr)
|
|||
|
||||
void abort ()
|
||||
{
|
||||
__stdio_cleanup();
|
||||
BS->Exit(IM, EFI_ABORTED, 0, NULL);
|
||||
}
|
||||
|
||||
void exit (int __status)
|
||||
{
|
||||
__stdio_cleanup();
|
||||
BS->Exit(IM, !__status ? 0 : (__status < 0 ? EFIERR(-__status) : EFIERR(__status)), 0, NULL);
|
||||
}
|
||||
|
||||
int exit_bs()
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_memory_descriptor_t *memory_map = NULL;
|
||||
uintn_t cnt = 3, memory_map_size=0, map_key=0, desc_size=0, i;
|
||||
__stdio_cleanup();
|
||||
while(cnt--) {
|
||||
status = BS->GetMemoryMap(&memory_map_size, memory_map, &map_key, &desc_size, NULL);
|
||||
if (status!=EFI_BUFFER_TOO_SMALL) break;
|
||||
status = BS->ExitBootServices(IM, map_key);
|
||||
if(!EFI_ERROR(status)) return 0;
|
||||
}
|
||||
return (int)(status & 0xffff);
|
||||
}
|
||||
|
||||
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, __compar_fn_t cmp)
|
||||
{
|
||||
uint64_t s=0, e=nmemb, m;
|
||||
|
@ -156,15 +174,17 @@ int mbtowc (wchar_t * __pwc, const char *s, size_t n)
|
|||
{
|
||||
wchar_t arg;
|
||||
const char *orig = s;
|
||||
int ret = 1;
|
||||
if(!s || !*s) return 0;
|
||||
arg = (wchar_t)*s;
|
||||
if((*s & 128) != 0) {
|
||||
if((*s & 32) == 0 && n > 0) { arg = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); } else
|
||||
if((*s & 16) == 0 && n > 1) { arg = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); } else
|
||||
if((*s & 8) == 0 && n > 2) { arg = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); }
|
||||
if((*s & 32) == 0 && n > 0) { arg = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); ret = 2; } else
|
||||
if((*s & 16) == 0 && n > 1) { arg = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); ret = 3; } else
|
||||
if((*s & 8) == 0 && n > 2) { arg = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); ret = 4; }
|
||||
else return -1;
|
||||
}
|
||||
if(__pwc) *__pwc = arg;
|
||||
return s - orig;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wctomb (char *s, wchar_t u)
|
||||
|
@ -190,14 +210,14 @@ size_t mbstowcs (wchar_t *__pwcs, const char *__s, size_t __n)
|
|||
{
|
||||
int r;
|
||||
wchar_t *orig = __pwcs;
|
||||
size_t ret = 0;
|
||||
if(!__s || !*__s) return 0;
|
||||
while(*__s) {
|
||||
r = mbtowc(__pwcs, __s, __n - ret);
|
||||
r = mbtowc(__pwcs, __s, __n - (__pwcs - orig));
|
||||
if(r < 0) return (size_t)-1;
|
||||
__pwcs++;
|
||||
__s += r;
|
||||
};
|
||||
}
|
||||
*__pwcs = 0;
|
||||
return __pwcs - orig;
|
||||
}
|
||||
|
||||
|
@ -206,12 +226,13 @@ size_t wcstombs (char *__s, const wchar_t *__pwcs, size_t __n)
|
|||
int r;
|
||||
char *orig = __s;
|
||||
if(!__s || !__pwcs || !*__pwcs) return 0;
|
||||
while(*__pwcs && (__s - orig + 3 < __n)) {
|
||||
while(*__pwcs && (__s - orig + 4 < __n)) {
|
||||
r = wctomb(__s, *__pwcs);
|
||||
if(r < 0) return (size_t)-1;
|
||||
__pwcs++;
|
||||
__s += r;
|
||||
};
|
||||
}
|
||||
*__s = 0;
|
||||
return __s - orig;
|
||||
}
|
||||
|
||||
|
@ -235,12 +256,19 @@ int rand()
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint8_t *getenv(wchar_t *name, uintn_t *len)
|
||||
uint8_t *getenv(char_t *name, uintn_t *len)
|
||||
{
|
||||
efi_guid_t globGuid = EFI_GLOBAL_VARIABLE;
|
||||
uint8_t tmp[EFI_MAXIMUM_VARIABLE_SIZE], *ret;
|
||||
uint32_t attr;
|
||||
efi_status_t status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
|
||||
efi_status_t status;
|
||||
#if USE_UTF8
|
||||
wchar_t wcname[256];
|
||||
mbstowcs((wchar_t*)&wcname, name, 256);
|
||||
status = RT->GetVariable((wchar_t*)&wcname, &globGuid, &attr, len, &tmp);
|
||||
#else
|
||||
status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
|
||||
#endif
|
||||
if(EFI_ERROR(status) || *len < 1 || !(ret = malloc((*len) + 1))) {
|
||||
*len = 0;
|
||||
return NULL;
|
||||
|
@ -250,9 +278,16 @@ uint8_t *getenv(wchar_t *name, uintn_t *len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int setenv(wchar_t *name, uintn_t len, uint8_t *data)
|
||||
int setenv(char_t *name, uintn_t len, uint8_t *data)
|
||||
{
|
||||
efi_guid_t globGuid = EFI_GLOBAL_VARIABLE;
|
||||
efi_status_t status = RT->SetVariable(name, &globGuid, 0, len, data);
|
||||
efi_status_t status;
|
||||
#if USE_UTF8
|
||||
wchar_t wcname[256];
|
||||
mbstowcs((wchar_t*)&wcname, name, 256);
|
||||
status = RT->SetVariable(wcname, &globGuid, 0, len, data);
|
||||
#else
|
||||
status = RT->SetVariable(name, &globGuid, 0, len, data);
|
||||
#endif
|
||||
return !EFI_ERROR(status);
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *strcpy(wchar_t *dst, const wchar_t *src)
|
||||
char_t *strcpy(char_t *dst, const char_t *src)
|
||||
{
|
||||
if(src && dst) {
|
||||
while(*src) {*dst++=*src++;} *dst=0;
|
||||
|
@ -127,16 +127,16 @@ wchar_t *strcpy(wchar_t *dst, const wchar_t *src)
|
|||
return dst;
|
||||
}
|
||||
|
||||
wchar_t *strncpy(wchar_t *dst, const wchar_t *src, size_t n)
|
||||
char_t *strncpy(char_t *dst, const char_t *src, size_t n)
|
||||
{
|
||||
const wchar_t *e = src+n;
|
||||
const char_t *e = src+n;
|
||||
if(src && dst && n>0) {
|
||||
while(*src && src<e) {*dst++=*src++;} *dst=0;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
wchar_t *strcat(wchar_t *dst, const wchar_t *src)
|
||||
char_t *strcat(char_t *dst, const char_t *src)
|
||||
{
|
||||
if(src && dst) {
|
||||
dst += strlen(dst);
|
||||
|
@ -145,7 +145,7 @@ wchar_t *strcat(wchar_t *dst, const wchar_t *src)
|
|||
return dst;
|
||||
}
|
||||
|
||||
int strcmp(const wchar_t *s1, const wchar_t *s2)
|
||||
int strcmp(const char_t *s1, const char_t *s2)
|
||||
{
|
||||
if(s1 && s2 && s1!=s2) {
|
||||
do{if(*s1!=*s2){return *s1-*s2;}s1++;s2++;}while(*s1!=0);
|
||||
|
@ -154,9 +154,9 @@ int strcmp(const wchar_t *s1, const wchar_t *s2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
wchar_t *strncat(wchar_t *dst, const wchar_t *src, size_t n)
|
||||
char_t *strncat(char_t *dst, const char_t *src, size_t n)
|
||||
{
|
||||
const wchar_t *e = src+n;
|
||||
const char_t *e = src+n;
|
||||
if(src && dst && n>0) {
|
||||
dst += strlen(dst);
|
||||
while(*src && src<e) {*dst++=*src++;} *dst=0;
|
||||
|
@ -164,9 +164,9 @@ wchar_t *strncat(wchar_t *dst, const wchar_t *src, size_t n)
|
|||
return dst;
|
||||
}
|
||||
|
||||
int strncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
|
||||
int strncmp(const char_t *s1, const char_t *s2, size_t n)
|
||||
{
|
||||
const wchar_t *e = s1+n;
|
||||
const char_t *e = s1+n;
|
||||
if(s1 && s2 && s1!=s2 && n>0) {
|
||||
do{if(*s1!=*s2){return *s1-*s2;}s1++;s2++;}while(*s1!=0 && s1<e);
|
||||
return *s1-*s2;
|
||||
|
@ -174,52 +174,52 @@ int strncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
wchar_t *strdup(const wchar_t *s)
|
||||
char_t *strdup(const char_t *s)
|
||||
{
|
||||
int i = (strlen(s)+1) * sizeof(wchar_t);
|
||||
wchar_t *s2 = (wchar_t *)malloc(i);
|
||||
int i = (strlen(s)+1) * sizeof(char_t);
|
||||
char_t *s2 = (char_t *)malloc(i);
|
||||
if(s2 != NULL) memcpy(s2, (void*)s, i);
|
||||
return s2;
|
||||
}
|
||||
|
||||
wchar_t *strchr(const wchar_t *s, int c)
|
||||
char_t *strchr(const char_t *s, int c)
|
||||
{
|
||||
if(s) {
|
||||
while(*s) {
|
||||
if(*s == (wchar_t)c) return (wchar_t*)s;
|
||||
if(*s == (char_t)c) return (char_t*)s;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *strrchr(const wchar_t *s, int c)
|
||||
char_t *strrchr(const char_t *s, int c)
|
||||
{
|
||||
wchar_t *e;
|
||||
char_t *e;
|
||||
if(s) {
|
||||
e = (wchar_t*)s + strlen(s) - 1;
|
||||
e = (char_t*)s + strlen(s) - 1;
|
||||
while(s < e) {
|
||||
if(*e == (wchar_t)c) return e;
|
||||
if(*e == (char_t)c) return e;
|
||||
s--;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *strstr(const wchar_t *haystack, const wchar_t *needle)
|
||||
char_t *strstr(const char_t *haystack, const char_t *needle)
|
||||
{
|
||||
return memmem(haystack, strlen(haystack) * sizeof(wchar_t), needle, strlen(needle) * sizeof(wchar_t));
|
||||
return memmem(haystack, strlen(haystack) * sizeof(char_t), needle, strlen(needle) * sizeof(char_t));
|
||||
}
|
||||
|
||||
wchar_t *_strtok_r(wchar_t *s, const wchar_t *d, wchar_t **p)
|
||||
char_t *_strtok_r(char_t *s, const char_t *d, char_t **p)
|
||||
{
|
||||
int c, sc;
|
||||
wchar_t *tok, *sp;
|
||||
char_t *tok, *sp;
|
||||
|
||||
if(d == NULL || (s == NULL && (s=*p) == NULL)) return NULL;
|
||||
again:
|
||||
c = *s++;
|
||||
for(sp = (wchar_t *)d; (sc=*sp++)!=0;) {
|
||||
for(sp = (char_t *)d; (sc=*sp++)!=0;) {
|
||||
if(c == sc) { *p=s; *(s-1)=0; return s-1; }
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ again:
|
|||
tok = s-1;
|
||||
while(1) {
|
||||
c = *s++;
|
||||
sp = (wchar_t *)d;
|
||||
sp = (char_t *)d;
|
||||
do {
|
||||
if((sc=*sp++) == c) {
|
||||
if(c == 0) s = NULL;
|
||||
|
@ -240,18 +240,18 @@ again:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *strtok(wchar_t *s, const wchar_t *delim)
|
||||
char_t *strtok(char_t *s, const char_t *delim)
|
||||
{
|
||||
wchar_t *p = s;
|
||||
char_t *p = s;
|
||||
return _strtok_r (s, delim, &p);
|
||||
}
|
||||
|
||||
wchar_t *strtok_r(wchar_t *s, const wchar_t *delim, wchar_t **ptr)
|
||||
char_t *strtok_r(char_t *s, const char_t *delim, char_t **ptr)
|
||||
{
|
||||
return _strtok_r (s, delim, ptr);
|
||||
}
|
||||
|
||||
size_t strlen (const wchar_t *__s)
|
||||
size_t strlen (const char_t *__s)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
|
|
75
uefi/uefi.h
75
uefi/uefi.h
|
@ -35,6 +35,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* comment out this if you want to use wchar_t in your application */
|
||||
#define USE_UTF8 1
|
||||
|
||||
/* get these from the compiler */
|
||||
typedef char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
@ -75,6 +78,14 @@ typedef uint64_t efi_physical_address_t;
|
|||
typedef uint64_t efi_virtual_address_t;
|
||||
typedef void *efi_handle_t;
|
||||
typedef void *efi_event_t;
|
||||
#if USE_UTF8
|
||||
typedef char char_t;
|
||||
#define CL(a) a
|
||||
extern char *__argvutf8;
|
||||
#else
|
||||
typedef wchar_t char_t;
|
||||
#define CL(a) L ## a
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t Data1;
|
||||
|
@ -1187,10 +1198,10 @@ typedef struct {
|
|||
struct dirent {
|
||||
unsigned short int d_reclen;
|
||||
unsigned char d_type;
|
||||
wchar_t d_name[FILENAME_MAX];
|
||||
char_t d_name[FILENAME_MAX];
|
||||
};
|
||||
typedef struct efi_file_handle_s DIR;
|
||||
extern DIR *opendir (const wchar_t *__name);
|
||||
extern DIR *opendir (const char_t *__name);
|
||||
extern struct dirent *readdir (DIR *__dirp);
|
||||
extern void rewinddir (DIR *__dirp);
|
||||
extern int closedir (DIR *__dirp);
|
||||
|
@ -1235,9 +1246,9 @@ extern int errno;
|
|||
/* stdlib.h */
|
||||
#define RAND_MAX 2147483647
|
||||
typedef int (*__compar_fn_t) (const void *, const void *);
|
||||
extern int atoi (const wchar_t *__nptr);
|
||||
extern int64_t atol (const wchar_t *__nptr);
|
||||
extern int64_t strtol (const wchar_t *__nptr, wchar_t **__endptr, int __base);
|
||||
extern int atoi (const char_t *__nptr);
|
||||
extern int64_t atol (const char_t *__nptr);
|
||||
extern int64_t strtol (const char_t *__nptr, char_t **__endptr, int __base);
|
||||
extern void *malloc (size_t __size);
|
||||
extern void *calloc (size_t __nmemb, size_t __size);
|
||||
extern void *realloc (void *__ptr, size_t __size);
|
||||
|
@ -1255,6 +1266,8 @@ extern size_t mbstowcs (wchar_t *__pwcs, const char *__s, size_t __n);
|
|||
extern size_t wcstombs (char *__s, const wchar_t *__pwcs, size_t __n);
|
||||
extern void srand(unsigned int __seed);
|
||||
extern int rand(void);
|
||||
extern uint8_t *getenv(char_t *name, uintn_t *len);
|
||||
extern int setenv(char_t *name, uintn_t len, uint8_t *data);
|
||||
|
||||
/* stdio.h */
|
||||
#ifndef BUFSIZ
|
||||
|
@ -1269,27 +1282,25 @@ extern int rand(void);
|
|||
typedef struct efi_file_handle_s FILE;
|
||||
extern int fclose (FILE *__stream);
|
||||
extern int fflush (FILE *__stream);
|
||||
extern int remove (const wchar_t *__filename);
|
||||
extern FILE *fopen (const wchar_t *__filename, const wchar_t *__modes);
|
||||
extern int remove (const char_t *__filename);
|
||||
extern FILE *fopen (const char_t *__filename, const char_t *__modes);
|
||||
extern size_t fread (void *__ptr, size_t __size, size_t __n, FILE *__stream);
|
||||
extern size_t fwrite (const void *__ptr, size_t __size, size_t __n, FILE *__s);
|
||||
extern int fseek (FILE *__stream, long int __off, int __whence);
|
||||
extern long int ftell (FILE *__stream);
|
||||
extern int feof (FILE *__stream);
|
||||
extern int fprintf (FILE *__stream, const wchar_t *__format, ...);
|
||||
extern int printf (const wchar_t *__format, ...);
|
||||
extern int sprintf (wchar_t *__s, const wchar_t *__format, ...);
|
||||
extern int vfprintf (FILE *__s, const wchar_t *__format, __builtin_va_list __arg);
|
||||
extern int vprintf (const wchar_t *__format, __builtin_va_list __arg);
|
||||
extern int vsprintf (wchar_t *__s, const wchar_t *__format, __builtin_va_list __arg);
|
||||
extern int snprintf (wchar_t *__s, size_t __maxlen, const wchar_t *__format, ...);
|
||||
extern int vsnprintf (wchar_t *__s, size_t __maxlen, const wchar_t *__format, __builtin_va_list __arg);
|
||||
extern int fprintf (FILE *__stream, const char_t *__format, ...);
|
||||
extern int printf (const char_t *__format, ...);
|
||||
extern int sprintf (char_t *__s, const char_t *__format, ...);
|
||||
extern int vfprintf (FILE *__s, const char_t *__format, __builtin_va_list __arg);
|
||||
extern int vprintf (const char_t *__format, __builtin_va_list __arg);
|
||||
extern int vsprintf (char_t *__s, const char_t *__format, __builtin_va_list __arg);
|
||||
extern int snprintf (char_t *__s, size_t __maxlen, const char_t *__format, ...);
|
||||
extern int vsnprintf (char_t *__s, size_t __maxlen, const char_t *__format, __builtin_va_list __arg);
|
||||
extern int getchar (void);
|
||||
/* non-blocking, only returns UNICODE if there's any key pressed, 0 otherwise */
|
||||
extern int getchar_ifany (void);
|
||||
extern int putchar (int __c);
|
||||
extern uint8_t *getenv(wchar_t *name, uintn_t *len);
|
||||
extern int setenv(wchar_t *name, uintn_t len, uint8_t *data);
|
||||
|
||||
/* string.h */
|
||||
#ifndef __clang__
|
||||
|
@ -1309,19 +1320,19 @@ extern void *memrchr (const void *__s, int __c, size_t __n);
|
|||
#endif
|
||||
void *memmem(const void *haystack, size_t hl, const void *needle, size_t nl);
|
||||
void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl);
|
||||
extern wchar_t *strcpy (wchar_t *__dest, const wchar_t *__src);
|
||||
extern wchar_t *strncpy (wchar_t *__dest, const wchar_t *__src, size_t __n);
|
||||
extern wchar_t *strcat (wchar_t *__dest, const wchar_t *__src);
|
||||
extern wchar_t *strncat (wchar_t *__dest, const wchar_t *__src, size_t __n);
|
||||
extern int strcmp (const wchar_t *__s1, const wchar_t *__s2);
|
||||
extern int strncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n);
|
||||
extern wchar_t *strdup (const wchar_t *__s);
|
||||
extern wchar_t *strchr (const wchar_t *__s, int __c);
|
||||
extern wchar_t *strrchr (const wchar_t *__s, int __c);
|
||||
extern wchar_t *strstr (const wchar_t *__haystack, const wchar_t *__needle);
|
||||
extern wchar_t *strtok (wchar_t *__s, const wchar_t *__delim);
|
||||
extern wchar_t *strtok_r (wchar_t *__s, const wchar_t *__delim, wchar_t **__save_ptr);
|
||||
extern size_t strlen (const wchar_t *__s);
|
||||
extern char_t *strcpy (char_t *__dest, const char_t *__src);
|
||||
extern char_t *strncpy (char_t *__dest, const char_t *__src, size_t __n);
|
||||
extern char_t *strcat (char_t *__dest, const char_t *__src);
|
||||
extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
|
||||
extern int strcmp (const char_t *__s1, const char_t *__s2);
|
||||
extern int strncmp (const char_t *__s1, const char_t *__s2, size_t __n);
|
||||
extern char_t *strdup (const char_t *__s);
|
||||
extern char_t *strchr (const char_t *__s, int __c);
|
||||
extern char_t *strrchr (const char_t *__s, int __c);
|
||||
extern char_t *strstr (const char_t *__haystack, const char_t *__needle);
|
||||
extern char_t *strtok (char_t *__s, const char_t *__delim);
|
||||
extern char_t *strtok_r (char_t *__s, const char_t *__delim, char_t **__save_ptr);
|
||||
extern size_t strlen (const char_t *__s);
|
||||
|
||||
/* sys/stat.h */
|
||||
#define S_IREAD 0400 /* Read by owner. */
|
||||
|
@ -1342,9 +1353,9 @@ struct stat {
|
|||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
};
|
||||
extern int stat (const wchar_t *__file, struct stat *__buf);
|
||||
extern int stat (const char_t *__file, struct stat *__buf);
|
||||
extern int fstat (FILE *__f, struct stat *__buf);
|
||||
extern int mkdir (const wchar_t *__path, mode_t __mode);
|
||||
extern int mkdir (const char_t *__path, mode_t __mode);
|
||||
|
||||
/* time.h */
|
||||
struct tm {
|
||||
|
|
Loading…
Reference in a new issue