libc: Document functions in headers #11

Merged
apio merged 12 commits from descriptive_headers into main 2022-10-12 10:11:45 +00:00
13 changed files with 207 additions and 87 deletions

View File

@ -7,6 +7,8 @@
#include "memory/VMM.h"
#include <stddef.h>
// FIXME: Round size up instead of down. (use get_blocks_from_size)
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
void sys_mmap(Context* context, void* address, size_t size, int flags)

View File

@ -1,15 +1,16 @@
#ifndef _ERRNO_H
#define _ERRNO_H
/* The last error encountered during a call to a library or system function. */
extern int errno;
#define EPERM 1
#define ENOENT 2
#define EBADF 9
#define ENOMEM 12
#define EISDIR 21
#define EINVAL 22
#define EMFILE 24
#define ENOSYS 38
#define EPERM 1 // Operation not permitted
#define ENOENT 2 // No such file or directory
#define EBADF 9 // Bad file descriptor
#define ENOMEM 12 // Cannot allocate memory
#define EISDIR 21 // Is a directory
#define EINVAL 22 // Invalid argument
#define EMFILE 24 // Too many open files
#define ENOSYS 38 // Function not implemented
#endif

View File

@ -1,8 +1,11 @@
#ifndef _FCNTL_H
#define _FCNTL_H
/* Open for reading only. */
#define O_RDONLY 1
/* Open for writing only. */
#define O_WRONLY 2
/* Open for reading and writing. */
#define O_RDWR 3
#ifdef __cplusplus
@ -10,7 +13,8 @@ extern "C"
{
#endif
int open(const char*, int);
/* Opens the file specified by pathname. Returns a file descriptor on success, or -1 on error. */
int open(const char* pathname, int flags);
#ifdef __cplusplus
}

View File

@ -9,8 +9,13 @@ extern "C"
{
#endif
/* Returns the current program's thread identifier. */
pid_t gettid();
unsigned int msleep(unsigned int);
/* Sleeps for ms milliseconds. */
unsigned int msleep(unsigned int ms);
/* Prints a message to standard error and aborts the program. */
noreturn void __luna_abort(const char* message);
#ifdef __cplusplus

View File

@ -13,8 +13,8 @@ typedef struct
int f_err;
} FILE;
extern FILE* __stderr;
extern FILE* __stdout;
extern FILE* __stderr; // The standard error stream.
extern FILE* __stdout; // The standard output stream.
#define stderr __stderr
#define stdout __stdout
@ -22,31 +22,80 @@ extern FILE* __stdout;
extern "C"
{
#endif
int fclose(FILE*);
int fflush(FILE*);
FILE* fopen(const char*, const char*);
int fprintf(FILE*, const char*, ...);
size_t fread(void*, size_t, size_t, FILE*);
/* Closes the file handle stream. */
int fclose(FILE* stream);
/* Does not do anything for now, since buffered IO is not implemented yet. */
int fflush(FILE* stream);
/* Opens the file specified by pathname. Returns the file handle on success, or NULL on error. */
FILE* fopen(const char* pathname, const char* mode);
/* Writes formatted output according to the string format to the file stream. */
int fprintf(FILE* stream, const char* format, ...);
/* Reads nmemb items of size size from the file stream into buf. */
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream);
int fseek(FILE*, long, int); // Not implemented.
long ftell(FILE*); // Not implemented.
size_t fwrite(const void*, size_t, size_t, FILE*);
int ferror(FILE*);
int feof(FILE*);
void clearerr(FILE*);
/* Writes nmemb items of size size from buf into the file stream. */
size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream);
/* Returns nonzero if the error flag in stream was set. */
int ferror(FILE* stream);
/* Returns nonzero if the end-of-file flag in stream was set. */
int feof(FILE* stream);
/* Clears the error and end-of-file flags from stream. */
void clearerr(FILE* stream);
void setbuf(FILE*, char*); // Not implemented.
int vfprintf(FILE*, const char*, va_list);
int printf(const char*, ...);
int vprintf(const char*, va_list);
int sprintf(char*, const char*, ...);
int snprintf(char*, size_t, const char*, ...);
int vsprintf(char*, const char*, va_list);
int vsnprintf(char*, size_t, const char*, va_list);
int puts(const char*);
int fputs(const char*, FILE*);
int fputc(int, FILE*);
int putc(int, FILE*);
int putchar(int);
void perror(const char*);
/* Writes formatted output according to the string format to the file stream. */
int vfprintf(FILE* stream, const char* format, va_list ap);
/* Writes formatted output according to the string format to standard output. */
int printf(const char* format, ...);
/* Writes formatted output according to the string format to standard output. */
int vprintf(const char* format, va_list ap);
/* Writes formatted output according to the string format to the string str. This function is unsafe, use snprintf
* instead. */
int sprintf(char* str, const char* format, ...);
/* Writes at most max bytes of formatted output according to the string format to the string str.*/
int snprintf(char* str, size_t max, const char* format, ...);
/* Writes formatted output according to the string format to the string str. This function is unsafe, use vsnprintf
* instead. */
int vsprintf(char* str, const char* format, va_list ap);
/* Writes at most max bytes of formatted output according to the string format to the string str. */
int vsnprintf(char* str, size_t max, const char* format, va_list ap);
/* Writes the string str followed by a trailing newline to stdout. */
int puts(const char* str);
/* Writes the string str to the file stream. */
int fputs(const char* str, FILE* stream);
/* Writes the character c to the file stream. */
int fputc(int c, FILE* stream);
/* Writes the character c to the file stream. */
int putc(int c, FILE* stream);
/* Writes the character c to standard output. */
int putchar(int c);
/* Prints a message to standard error consisting of the string str followed by a colon and the string representation
* of the last error encountered during a call to a system or library function. */
void perror(const char* str);
#ifdef __cplusplus
}

View File

@ -9,13 +9,37 @@ extern "C"
{
#endif
/* Aborts the program. */
noreturn void abort();
noreturn void exit(int);
/* Exits the program with the specified status code. */
noreturn void exit(int status);
/* Not implemented. */
int atexit(void (*)(void));
/* Not implemented.*/
int atoi(const char*);
void free(void*);
/* Not implemented. */
char* getenv(const char*);
void* malloc(size_t);
/* Allocates n bytes of memory and returns a pointer to it. This memory should be freed by calling free() when it is
* not in use anymore. */
void* malloc(size_t n);
/* Allocates enough bytes of memory for an array containing nmemb items of size n and returns a pointer to it. This
* memory should be freed by calling free() when it is not in use anymore. */
void* calloc(size_t nmemb, size_t n);
/* Resizes memory allocated by malloc() or calloc() to n bytes. Returns a pointer to the new resized region of
* memory, which should be used instead of the old one. This memory should be freed by calling free() when it is not
* in use anymore. */
void* realloc(void* ptr, size_t n);
/* Frees a pointer to memory allocated by malloc(), calloc() or realloc(). Accessing the contents of ptr afterwards
* is undefined behavior. */
void free(void* ptr);
#ifdef __cplusplus
}

View File

@ -9,21 +9,37 @@ extern "C"
{
#endif
void* memcpy(void*, const void*, size_t);
void* memset(void*, int, size_t);
void* memclr(void*, size_t);
/* Copies n bytes from src to dst. */
void* memcpy(void* dest, const void* src, size_t n);
size_t strlen(const char*);
/* Sets n bytes of buf to c, cast to a character. */
void* memset(void* buf, int c, size_t n);
deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char*, const char*);
char* strncpy(char*, const char*, size_t);
/* Clears n bytes of buf. */
void* memclr(void* buf, size_t n);
char* strchr(const char*, int);
/* Returns the length of the string str. */
size_t strlen(const char* str);
deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char*, const char*);
char* strncat(char*, const char*, size_t);
/* Copies the string src into dest. This function is unsafe, use strncpy instead. */
deprecated("strcpy is unsafe and should not be used; use strncpy instead") char* strcpy(char* dest,
const char* src);
char* strerror(int);
/* Copies at most max bytes from the string src into dest. */
char* strncpy(char* dest, const char* src, size_t max);
/* Returns a pointer to the first occurrence of the character c in str, or NULL if it is not found. */
char* strchr(const char* str, int c);
/* Concatenates the string src into dest. This function is unsafe, use strncat instead. */
deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char* dest,
const char* src);
/* Concatenates at most max bytes of the string src into dest. */
char* strncat(char* dest, const char* src, size_t max);
/* Returns the error string associated with the error number err. */
char* strerror(int err);
#ifdef __cplusplus
}

View File

@ -5,6 +5,7 @@
typedef unsigned long off_t;
/* Address returned by mmap when it fails. */
#define MAP_FAILED (void*)-1
#define PROT_READ_WRITE 1
@ -16,8 +17,13 @@ extern "C"
{
#endif
void* mmap(void*, size_t, int, int, int, off_t);
int munmap(void* addr, size_t len);
/* Maps size bytes of memory (rounded down to the nearest page-aligned size) into the current process's address
* space at addr. If addr is null, the kernel will choose an address. */
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset);
/* Unmaps size bytes of memory (rounded down to the nearest page-aligned size) at addr from the current process's
* address space. */
int munmap(void* addr, size_t size);
#ifdef __cplusplus
}

View File

@ -1,8 +1,13 @@
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
/* The type of a process identifier. */
typedef long int pid_t;
/* The type returned by sizeof(). */
typedef unsigned long int size_t;
/* Signed version of size_t. */
typedef long int ssize_t;
#endif

View File

@ -8,16 +8,29 @@ extern "C"
{
#endif
/* Not implemented. */
int execv(const char*, char* const[]);
/* Not implemented. */
int execve(const char*, char* const[], char* const[]);
/* Not implemented. */
int execvp(const char*, char* const[]);
/* Not implemented. */
pid_t fork(void);
long syscall(long, ...);
unsigned int sleep(unsigned int);
ssize_t read(int, void*, size_t);
ssize_t write(int, const void*, size_t);
int close(int);
/* Calls the kernel for a specific service, determined by number. */
long syscall(long number, ...);
/* Suspends execution for a chosen amount of seconds. */
unsigned int sleep(unsigned int seconds);
/* Reads count bytes from the file descriptor fd into the memory at buf. */
ssize_t read(int fd, void* buf, size_t count);
/* Writes count bytes of the memory at buf to the file descriptor fd. */
ssize_t write(int fd, const void* buf, size_t count);
/* Closes the file descriptor fd. */
int close(int fd);
#ifdef __cplusplus
}

View File

@ -5,8 +5,6 @@
#include <sys/syscall.h>
#include <unistd.h>
#define noreturn __attribute__((noreturn))
extern "C"
{
pid_t gettid()
@ -21,7 +19,7 @@ extern "C"
noreturn void __luna_abort(const char* message)
{
fwrite(message, strlen(message), 1, stdout);
fputs(message, stderr);
abort();
}
}

View File

@ -3,11 +3,6 @@
#include <sys/syscall.h>
#include <unistd.h>
#define noreturn __attribute__((noreturn))
#define maybe_unused __attribute__((maybe_unused))
#define unused __attribute__((unused))
extern "C"
{
noreturn void abort()
@ -25,10 +20,12 @@ extern "C"
{
NOT_IMPLEMENTED("atexit");
}
int atoi(const char*)
{
NOT_IMPLEMENTED("atoi");
}
char* getenv(const char*)
{
NOT_IMPLEMENTED("getenv");

View File

@ -10,18 +10,18 @@ extern "C"
return dest;
}
void* memset(void* dest, int c, size_t n)
void* memset(void* buf, int c, size_t n)
{
for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = (char)c; }
return dest;
for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; }
return buf;
}
size_t strlen(const char* s)
size_t strlen(const char* str)
{
const char* i = s;
const char* i = str;
for (; *i; ++i)
;
return (i - s);
return (i - str);
}
char* strcpy(char* dest, const char* src)
@ -30,10 +30,10 @@ extern "C"
return dest;
}
char* strncpy(char* dest, const char* src, size_t n)
char* strncpy(char* dest, const char* src, size_t max) // FIXME: Implement strncpy according to the specification.
{
size_t src_len = strlen(src) + 1; // NULL byte
memcpy(dest, src, src_len > n ? n : src_len);
memcpy(dest, src, src_len > max ? max : src_len);
return dest;
}
@ -49,40 +49,40 @@ extern "C"
return dest;
}
char* strncat(char* dest, const char* src, size_t n)
char* strncat(char* dest, const char* src, size_t max)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0; i < n && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i);
for (i = 0; i < max && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i);
*(char*)(dest + dest_len + i) = '\0';
return dest;
}
char* strchr(const char* str, int chr)
char* strchr(const char* str, int c)
{
while (*str && *str != (char)chr) str++;
while (*str && *str != (char)c) str++;
if (*str) return const_cast<char*>(str);
return NULL;
}
void* memclr(void* start, size_t count)
void* memclr(void* buf, size_t n)
{
// "i" is our counter of how many bytes we've cleared
size_t i;
// find out if "m_start" is aligned on a SSE_XMM_SIZE boundary
if ((size_t)start & (15))
if ((size_t)buf & (15))
{
i = 0;
// we need to clear byte-by-byte until "m_start" is aligned on an SSE_XMM_SIZE boundary
// ... and lets make sure we don't copy 'too' many bytes (i < m_count)
while (((size_t)start + i) & (15) && i < count)
while (((size_t)buf + i) & (15) && i < n)
{
asm("stosb;" ::"D"((size_t)start + i), "a"(0));
asm("stosb;" ::"D"((size_t)buf + i), "a"(0));
i++;
}
}
@ -93,42 +93,42 @@ extern "C"
}
// clear 64-byte chunks of memory (4 16-byte operations)
for (; i + 64 <= count; i += 64)
for (; i + 64 <= n; i += 64)
{
asm volatile(" pxor %%xmm0, %%xmm0; " // set XMM0 to 0
" movdqa %%xmm0, 0(%0); " // move 16 bytes from XMM0 to %0 + 0
" movdqa %%xmm0, 16(%0); "
" movdqa %%xmm0, 32(%0); "
" movdqa %%xmm0, 48(%0); " ::"r"((size_t)start + i));
" movdqa %%xmm0, 48(%0); " ::"r"((size_t)buf + i));
}
// copy the remaining bytes (if any)
asm(" rep stosb; " ::"a"((size_t)(0)), "D"(((size_t)start) + i), "c"(count - i));
asm(" rep stosb; " ::"a"((size_t)(0)), "D"(((size_t)buf) + i), "c"(n - i));
// "i" will contain the total amount of bytes that were actually transfered
i += count - i;
i += n - i;
// we return "m_start" + the amount of bytes that were transfered
return (void*)(((size_t)start) + i);
return (void*)(((size_t)buf) + i);
}
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wwrite-strings"
char* strerror(int errnum)
char* strerror(int err)
{
switch (errnum)
switch (err)
{
case EPERM: return "Operation not permitted";
case EINVAL: return "Invalid argument";
case ENOMEM: return "Out of memory";
case ENOMEM: return "Cannot allocate memory";
case ENOSYS: return "Function not implemented";
case ENOENT: return "No such file or directory";
case EBADF: return "Bad file descriptor";
case EMFILE: return "Too many open files";
case EISDIR: return "Is a directory";
case 0: return "Success";
default: return (char*)(unsigned long int)errnum;
default: return (char*)(unsigned long int)err;
}
}