-#ifndef _STDLIB_H_\r
-#define _STDLIB_H_\r
+#ifndef _COMMONLIB_H_\r
+#define _COMMONLIB_H_\r
#include <stdio.h>\r
#include <stdbool.h>\r
#include <stdarg.h>\r
#include <stdlib.h>\r
#include <string.h>\r
#include <ctype.h>\r
-#ifdef _WIN32\r
-#include <windows.h>\r
-#endif\r
#include <locale.h>\r
\r
\r
typedef const char* cstr;\r
typedef const wchar* wstr;\r
\r
-#define ASSERT(condition) if (!(condition)) panic_assertion(#condition, stderr, __FILE__, __LINE__)\r
+#define ASSERT(condition, msg) do {\\r
+ if (!(condition)) {\\r
+ fprintf(stderr, "%s:%d:0 [ASSERTION FAILED] %s: %s", __FILE__, __LINE__, #condition, msg);\\r
+ exit(1);\\r
+ }\\r
+ } while (0)\r
\r
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))\r
\r
#define STRUCT(name) typedef struct name name\r
#define ENUM(name) typedef enum name name\r
-#define DYNAMIC_ARRAY(type, name) type* name = NULL\r
\r
// Struct pre-decls\r
\r
STRUCT(Arena);\r
\r
-void panic_assertion(cstr msg, FILE* file, cstr filename, int line);\r
-\r
//\r
// OS\r
//\r
\r
void os_get_timedate(Arena* a);\r
bool os_file_exists(cstr filename);\r
+\r
//\r
-// Winapi\r
-//\r
-#ifdef _WIN32\r
-#define WINAPI_ERROR_MSG_BUFF_SIZE 1024\r
-static char winapi_error_msg_buff[WINAPI_ERROR_MSG_BUFF_SIZE];\r
-#define WINAPI_OUTPUT_STR_BUFF_SIZE (16*1024)\r
-static CHAR_INFO winapi_output_str_buff[WINAPI_OUTPUT_STR_BUFF_SIZE];\r
-\r
-bool output_str(cstr text);\r
-bool output_strn(cstr text, size_t text_len);\r
-cstr winapi_get_last_error_str(void);\r
-cstr winapi_get_current_working_directory(Arena* arena);\r
-#endif // _WIN32\r
-#ifdef linux\r
-#include <sys/stat.h>\r
-#endif // linux\r
-//\r
-// logging\r
+// Logging\r
//\r
\r
// FLUSH_ON_LOG - define this macro to fflush() on every call to log() not defined by default.\r
\r
-typedef enum {\r
- C_LOG_INFO = 0,\r
- C_LOG_ERROR,\r
- C_LOG_WARNING,\r
- C_LOG_COUNT,\r
-} Log_type;\r
-\r
-void log_file(Log_type type, FILE* file, cstr fmt, ...);\r
-#define log_f(type, fmt, ...) log_file(type, stdout, fmt, ##__VA_ARGS__)\r
-#define log_info(fmt, ...) log_f(C_LOG_INFO, fmt, ##__VA_ARGS__)\r
-#define log_error(fmt, ...) log_f(C_LOG_ERROR, fmt, ##__VA_ARGS__)\r
-#define log_warning(fmt, ...) log_f(C_LOG_WARNING, fmt, ##__VA_ARGS__)\r
+#define log_info(fmt, ...) printf("%s "fmt"\n", "[INFO]", ##__VA_ARGS__)\r
+#define log_warning(fmt, ...) fprintf(stderr, "%s "fmt"\n", "[WARNING]", ##__VA_ARGS__)\r
+#define log_error(fmt, ...) fprintf(stderr, "%s "fmt"\n", "[ERROR]", ##__VA_ARGS__)\r
\r
//\r
// File\r
\r
// reads entire file and gives back the string holding the contents. (caller must be responsible for freeing the string!)\r
const char* slurp_file(const char* filename, bool* success);\r
-void touch_file_if_doesnt_exist(cstr file);\r
+// void touch_file_if_doesnt_exist(cstr file);\r
\r
//\r
// ### Allocators ###\r
\r
cstr shift_args(int* argc, char*** argv);\r
\r
-#endif /* _STDLIB_H_ */\r
+#endif /* _COMMONLIB_H_ */\r
\r
//////////////////////////////////////////////////\r
#ifdef COMMONLIB_IMPLEMENTATION\r
// OS\r
//\r
\r
-#ifdef _WIN32\r
+#if defined(_WIN32) || defined(__CYGWIN__)\r
void os_get_timedate(Arena* a) {\r
(void)a;\r
+ ASSERT(false, "Unimplemented!");\r
}\r
\r
bool os_file_exists(cstr filename) {\r
(void) filename;\r
+ ASSERT(false, "Unimplemented!");\r
return false;\r
}\r
\r
-#endif // _WIN32\r
-#ifdef linux\r
+#elif defined(__linux__)\r
void os_get_timedate(Arena* a) {\r
(void)a;\r
+ ASSERT(false, "Unimplemented!");\r
}\r
\r
bool os_file_exists(cstr filename) {\r
struct stat buf;\r
+ ASSERT(false, "Unimplemented!");\r
return stat(filename, &buf) == 0;\r
}\r
-\r
-#endif // linux\r
-\r
-#ifdef _WIN32\r
-// Winapi\r
-cstr winapi_get_last_error_str(void) {\r
- DWORD error_code = GetLastError();\r
- if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, winapi_error_msg_buff, WINAPI_ERROR_MSG_BUFF_SIZE, NULL)){\r
- log_f(C_LOG_ERROR, "FormatMessage() failed with code: %d", GetLastError());\r
- return NULL;\r
- }\r
- return winapi_error_msg_buff;\r
-}\r
-\r
-cstr winapi_get_current_working_directory(Arena* arena) {\r
- if (arena->buff_size < MAX_PATH) {\r
- log_error("Arena size should be at least of size MAX_PATH(%u)", MAX_PATH);\r
- return NULL;\r
- }\r
-\r
- size_t n = GetCurrentDirectoryA((DWORD)arena->buff_size, arena->buff);\r
- if (n == 0) {\r
- log_error("%s -> %s", __func__, winapi_get_last_error_str());\r
- return NULL;\r
- }\r
- return arena->buff;\r
-}\r
-\r
-bool output_str(cstr text) {\r
- return output_strn(text, strlen(text));\r
-}\r
-\r
-bool output_strn(cstr text, size_t text_len) {\r
- SECURITY_ATTRIBUTES sa = {0};\r
- sa.nLength = sizeof(sa);\r
- sa.bInheritHandle = TRUE;\r
-\r
- HANDLE console = CreateFileA("CONOUT$",\r
- GENERIC_READ|GENERIC_WRITE,\r
- FILE_SHARE_WRITE,\r
- &sa,\r
- OPEN_EXISTING,\r
- 0,\r
- NULL);\r
-\r
- if (console == INVALID_HANDLE_VALUE) {\r
- log_f(C_LOG_INFO, "Could not get a handle to the active console screen buffer: %s", winapi_get_last_error_str());\r
- return 1;\r
- }\r
-\r
- if (text_len == 0) return false;\r
-\r
- ASSERT(text_len < WINAPI_OUTPUT_STR_BUFF_SIZE);\r
- CHAR_INFO* buff = winapi_output_str_buff;\r
-\r
- CONSOLE_SCREEN_BUFFER_INFO csbi = {0};\r
-\r
- if (!GetConsoleScreenBufferInfo(console, &csbi)) {\r
- log_f(C_LOG_ERROR, "Could not get console screen buffer info: %s", winapi_get_last_error_str());\r
- return false;\r
- }\r
-\r
- COORD buff_size = {0, 1};\r
- COORD new_cursor = {\r
- .X = csbi.dwCursorPosition.X,\r
- .Y = csbi.dwCursorPosition.Y\r
- };\r
-\r
- bool overflown = false;\r
-\r
- char* next_text = NULL;\r
-\r
- for (size_t i = 0; i < text_len; ++i) {\r
- if (text[i] == '\n') {\r
- overflown = true;\r
- next_text = (char*)text+buff_size.X+1;\r
- text_len = (text+text_len)-text;\r
- break;\r
- } else {\r
- buff[i].Char.AsciiChar = text[i];\r
- buff_size.X++;\r
- new_cursor.X++;\r
- if (new_cursor.X >= csbi.dwMaximumWindowSize.X) {\r
- overflown = true;\r
- next_text = (char*)text+buff_size.X;\r
- text_len = (text+text_len)-text;\r
- break;\r
- }\r
- }\r
-\r
- buff[i].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY;\r
- }\r
-\r
- COORD write_coord = {0, 0};\r
- SMALL_RECT rect = {\r
- .Left = csbi.dwCursorPosition.X,\r
- .Top = csbi.dwCursorPosition.Y,\r
- .Right = new_cursor.X,\r
- .Bottom = new_cursor.Y,\r
- };\r
-\r
- if(!WriteConsoleOutput(console,\r
- buff,\r
- buff_size,\r
- write_coord,\r
- &rect)) {\r
- log_f(C_LOG_ERROR, "[1] Could not write to console output: [%d] %s", GetLastError(), winapi_get_last_error_str());\r
- return false;\r
- }\r
-\r
- if (!overflown) {\r
- // advance cursor\r
- if (!SetConsoleCursorPosition(console, new_cursor)) {\r
- log_f(C_LOG_ERROR, "[1] Could not set new cursor pos: %s", winapi_get_last_error_str());\r
- return false;\r
- }\r
- }\r
-\r
- if (overflown) {\r
- new_cursor.X = 0;\r
- new_cursor.Y++;\r
- // advance cursor\r
- if (!SetConsoleCursorPosition(console, new_cursor)) {\r
- log_f(C_LOG_ERROR, "[2] Could not set new cursor pos: %s", winapi_get_last_error_str());\r
- return false;\r
- }\r
- output_strn(next_text, text_len);\r
- }\r
-\r
- return true;\r
-}\r
-\r
-#endif // _WIN32\r
-\r
-void panic_assertion(cstr msg, FILE* file, cstr filename, int line) {\r
- fprintf(file, "%s:%d:0: ASSERTION FAILED: %s\n", filename, line, msg);\r
- exit(1);\r
-}\r
-\r
-void log_file(Log_type type, FILE* file, cstr fmt, ...) {\r
- va_list args;\r
- va_start(args, fmt);\r
-\r
- // SYSTEMTIME sys_time = {0};\r
- // GetLocalTime(&sys_time);\r
-\r
- // fprintf(file, "[%02d:%02d:%02d] ", sys_time.wHour, sys_time.wMinute, sys_time.wSecond);\r
-\r
- switch (type){\r
- case C_LOG_INFO: fprintf(file, "INFO: "); break;\r
- case C_LOG_ERROR: fprintf(file, "ERROR: "); break;\r
- case C_LOG_WARNING: fprintf(file, "WARNING: "); break;\r
- case C_LOG_COUNT:\r
- default: ASSERT(0 && "Unreachable");\r
- }\r
-\r
- while (*fmt != '\0'){\r
- if (*fmt == '%'){\r
- fmt++;\r
- switch (*fmt){\r
- case 's': {\r
- const char* str = va_arg(args, const char*);\r
- fprintf(file, "%s", str);\r
- } break;\r
- case 'i':\r
- case 'd': {\r
- int i = va_arg(args, int);\r
- fprintf(file, "%d", i);\r
- } break;\r
- case 'o': {\r
- int i = va_arg(args, int);\r
- fprintf(file, "%o", i);\r
- } break;\r
- case 'u': {\r
- unsigned int i = va_arg(args, unsigned int);\r
- fprintf(file, "%u", i);\r
- } break;\r
- case 'f':\r
- case 'F': {\r
- double i = va_arg(args, double);\r
- fprintf(file, "%f", i);\r
- } break;\r
- case 'p': {\r
- void* i = va_arg(args, void*);\r
- fprintf(file, "%p", i);\r
- } break;\r
- case '%': {\r
- fprintf(file, "%%");\r
- } break;\r
- case 'c':{\r
- int i = va_arg(args, int);\r
- fprintf(file, "%c", i);\r
- } break;\r
- }\r
- } else {\r
- fputc(*fmt, file);\r
- }\r
- fmt++;\r
- }\r
-\r
- fputc('\n', file);\r
-#ifdef FLUSH_ON_LOG\r
- fflush(file);\r
#endif\r
- va_end(args);\r
-}\r
\r
// simple and dirty way to have defering in C (not recommended to use!)\r
#define defer(ret_val) \\r
char* result = NULL;\r
\r
if (f == NULL){\r
- log_f(C_LOG_ERROR, "slurp_file::fopen(\"%s\", \"rb\") -> %s\n", filename, strerror(errno));\r
+ log_error("slurp_file::fopen(\"%s\", \"rb\") -> %s\n", filename, strerror(errno));\r
defer(NULL);\r
}\r
\r
if (fseek(f, 0, SEEK_END) < 0) {\r
- log_f(C_LOG_ERROR, "slurp_file::fseek(f, 0, SEEK_END) -> %s\n", filename, strerror(errno));\r
+ log_error("slurp_file::fseek(f, 0, SEEK_END) -> %s\n", filename, strerror(errno));\r
defer(NULL);\r
}\r
\r
size_t fsize = ftell(f);\r
\r
if (fsize == (size_t)-1){\r
- log_f(C_LOG_ERROR, "slurp_file::ftell(f) -> %s\n", filename, strerror(errno));\r
+ log_error("slurp_file::ftell(f) -> %s\n", filename, strerror(errno));\r
defer(NULL);\r
}\r
\r
result = malloc(sizeof(char)*(fsize+1));\r
\r
if (result == NULL){\r
- log_f(C_LOG_ERROR, "slurp_file::malloc(%zu) -> %s\n", sizeof(char)*fsize, strerror(errno));\r
+ log_error("slurp_file::malloc(%zu) -> %s\n", sizeof(char)*fsize, strerror(errno));\r
defer(NULL);\r
}\r
\r
if (fseek(f, 0, SEEK_SET) < 0) {\r
- log_f(C_LOG_ERROR, "slurp_file::fseek(f, 0, SEEK_SET) -> %s\n", filename, strerror(errno));\r
+ log_error("slurp_file::fseek(f, 0, SEEK_SET) -> %s\n", filename, strerror(errno));\r
defer(NULL);\r
}\r
\r
if (fread((char*)result, sizeof(char), fsize, f) != fsize){\r
- log_f(C_LOG_ERROR, "slurp_file::fread(result, %d, 1, f) -> %s\n", fsize, strerror(errno));\r
+ log_error("slurp_file::fread(result, %d, 1, f) -> %s\n", fsize, strerror(errno));\r
defer(NULL);\r
}\r
\r
return result;\r
}\r
\r
-void touch_file_if_doesnt_exist(cstr filename) {\r
- if (os_file_exists(filename)) return;\r
- FILE* file = fopen(filename, "w");\r
- if (file)\r
- fclose(file);\r
-}\r
+// void touch_file_if_doesnt_exist(cstr filename) {\r
+// if (os_file_exists(filename)) return;\r
+// FILE* file = fopen(filename, "w");\r
+// if (file)\r
+// fclose(file);\r
+// }\r
\r
//\r
// ### Allocators ###\r
res.buff = malloc(res.buff_size);\r
res.ptr = res.buff;\r
\r
- ASSERT(res.buff);\r
+ ASSERT(res.buff, "Malloc failed?");\r
\r
return res;\r
}\r
\r
void* Arena_alloc(Arena* a, size_t size) {\r
- ASSERT(a->buff);\r
+ ASSERT(a->buff, "Bro pass an initialized arena!");\r
\r
void* res = a->ptr;\r
a->ptr = (uint8*)a->ptr + size;\r