/// _ _ _ /// | | | | | | /// __ _| |_ __ _ _ __ __| | __ _ _ __ __| | /// \ \/ / __/ _` | '_ \ / _` |/ _` | '__/ _` | /// > <| || (_| | | | | (_| | (_| | | | (_| | /// /_/\_\\__\__,_|_| |_|\__,_|\__,_|_| \__,_| /// /// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic /// /// xolatile@chud.cyou - xtandard - Tiny, safe and somewhat sane unity header for what GNU/Linux already provides. /// /// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU /// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish... /// /// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied /// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License /// for more details, if you dare, it is a lot of text that nobody wants to read... #define _GNU_SOURCE #include #include #include #include #include #include #include #define null ((void *) 0) #define standard_input (STDIN_FILENO) #define standard_output (STDOUT_FILENO) #define standard_error (STDERR_FILENO) #define file_flag_read (O_RDONLY) #define file_flag_write (O_WRONLY) #define file_flag_edit (O_RDWR) #define file_flag_create (O_CREAT) #define file_flag_append (O_APPEND) #define file_flag_truncate (O_TRUNC) #define file_seek_current (SEEK_CUR) #define file_seek_set (SEEK_SET) #define file_seek_end (SEEK_END) #define echo(text) output ((text), sizeof ((text)) - 1) #define maximum(x, y) (((x) > (y)) ? (x) : (y)) #define minimum(x, y) (((x) < (y)) ? (x) : (y)) #define array_length(array) (sizeof ((array)) / sizeof (* (array))) typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef char pstring [256]; typedef enum { false, true } bool; typedef enum { log_success, log_warning, log_failure, log_comment, log_count } log_enumeration; typedef enum { file_type_c_source, file_type_c_header, file_type_ada_sexy_body, file_type_ada_specification, file_type_cpp_source, file_type_cpp_header, file_type_fortran_90_source, file_type_fortran_90_module, file_type_pascal_source, file_type_d_source, file_type_go_source, file_type_jai_source, file_type_assembly, file_type_eax_assembly, file_type_gnu_assembly, file_type_flat_assembly, file_type_haskell_script, file_type_perl_script, file_type_cube_script, file_type_lua_script, file_type_shell_script, file_type_python_script, file_type_tcl_script, file_type_forth_source, file_type_text, file_type_markdown, file_type_html, file_type_glsl, file_type_xrocessor, file_type_xhla, file_type_xcript, file_type_xocument, file_type_xiri, file_type_xofya, file_type_xienna, file_type_xenka, file_type_xiyagi, file_type_xoule, file_type_xikoku, file_type_xdo, file_type_png_image, file_type_jxl_image, file_type_jpg_image, file_type_tga_image, file_type_wav_sound, file_type_ogg_sound, file_type_flac_sound, file_type_mp3_sound, file_type_obj_model, file_type_iqm_model, file_type_md5_model, file_type_ply_model, file_type_elf_object, file_type_spir_v_bytecode, file_type_count } file_type_enumeration; typedef enum { effect_normal, effect_bold, effect_italic, effect_undefined_code, effect_underline, effect_blink, effect_reverse, effect_invisible_text, effect_count } effect_enumeration; typedef enum { colour_grey, colour_red, colour_green, colour_yellow, colour_blue, colour_pink, colour_cyan, colour_white, colour_count } colour_enumeration; typedef enum { character_null, character_start_header, character_start_text, character_end_text, character_end_transmission, character_enquiry, character_acknowledge, character_bell, character_backspace, character_tab_horizontal, character_line_feed, character_tab_vertical, character_form_feed, character_carriage_return, character_shift_out, character_shift_in, character_data_link_escape, character_device_control_1, character_device_control_2, character_device_control_3, character_device_control_4, character_not_acknowledge, character_synchronous_idle, character_end_transmission_block, character_cancel, character_end_medium, character_substitute, character_escape, character_file_separator, character_group_separator, character_record_separator, character_unit_separator } character_enumeration; typedef enum { cursor_none, cursor_left, cursor_middle, cursor_right, cursor_wheel_up, cursor_wheel_down, cursor_count } cursor_enumeration; typedef enum { signal_none, signal_a, signal_b, signal_c, signal_d, signal_e, signal_f, signal_g, signal_h, signal_i, signal_j, signal_k, signal_l, signal_m, signal_n, signal_o, signal_p, signal_q, signal_r, signal_s, signal_t, signal_u, signal_v, signal_w, signal_x, signal_y, signal_z, signal_0, signal_1, signal_2, signal_3, signal_4, signal_5, signal_6, signal_7, signal_8, signal_9, signal_escape, signal_tabulator, signal_return, signal_new_line, signal_slash, signal_backslash, signal_semicolon, signal_backquote, signal_space, signal_backspace, signal_dot, signal_comma, signal_cite, signal_caps_lock, signal_minus, signal_equal, signal_left_bracket, signal_right_bracket, signal_left_control, signal_right_control, signal_left_shift, signal_right_shift, signal_left_alt, signal_right_alt, signal_f1, signal_f2, signal_f3, signal_f4, signal_f5, signal_f6, signal_f7, signal_f8, signal_f9, signal_f10, signal_f11, signal_f12, signal_arrow_up, signal_arrow_down, signal_arrow_left, signal_arrow_right, signal_num_lock, signal_pause_break, signal_insert, signal_home, signal_page_up, signal_delete, signal_end, signal_page_down, signal_key_add, signal_key_subtract, signal_key_multiply, signal_key_divide, signal_key_enter, signal_key_dot, signal_key_0, signal_key_1, signal_key_2, signal_key_3, signal_key_4, signal_key_5, signal_key_6, signal_key_7, signal_key_8, signal_key_9, signal_count } signal_enumeration; static const char * cursor_name [cursor_count] = { "---", "Left button", "Middle button", "Right button", "Scroll up", "Scroll down" }; static const char * signal_name [signal_count] = { "---", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Escape", "Tabulator", "Return", "New line", "Slash", "Backslash", "Semicolon", "Backquote", "Space", "Backspace", "Dot", "Comma", "Cite", "Caps lock", "Minus", "Equal", "Left bracket", "Right bracket", "Left control", "Right control", "Left shift", "Right shift", "Left alt", "Right alt", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Arrow up", "Arrow down", "Arrow left", "Arrow right", "Num lock", "Pause break", "Insert", "Home", "Page up", "Delete", "End", "Page down", "Key add", "Key subtract", "Key multiply", "Key divide", "Key enter", "Key dot", "Key 0", "Key 1", "Key 2", "Key 3", "Key 4", "Key 5", "Key 6", "Key 7", "Key 8", "Key 9" }; static void randomize_seed_by_time (void) { srand ((uint) time (null)); } static int randomize (int from, int to) { return (rand () % (to - from + 1) + from); } static uint urandomize (uint from, uint to) { return ((uint) rand () % (to - from + 1) + from); } static float frandomize (float from, float to) { return (((float) rand () / (float) RAND_MAX) * (to - from) + from); } static int upper_bound (int a, int b) { return ((a > b) ? a : b); } static int lower_bound (int a, int b) { return ((a < b) ? a : b); } static void input (void * data, ulong size) { read (standard_input, data, size); } static void output (const void * data, ulong size) { write (standard_output, data, size); } static void clean_up (void (* procedure) (void)) { atexit (procedure); } #ifdef use_fatal_failure static void fatal_failure (bool condition, const char * message) { if (condition == true) { echo ("[\x1b[1;31m FATAL \x1b[0m] "); for (int index = 0; message [index] != '\0'; ++index) { output (& message [index], 1); } echo ("\n"); exit (log_failure); } } #else #define fatal_failure(...) #endif static void execute (const char * command) { int status = 0; system (command); fatal_failure (status != 0, "execute: System returned an error code."); } static uint tick_tock (void) { return ((uint) clock ()); } static ulong nano_time (void) { struct timespec time = { 0 }; ulong result = 0; clock_gettime (CLOCK_MONOTONIC, & time); result = 1000000000ul * (ulong) time.tv_sec + (ulong) time.tv_nsec; return (result); } static void nano_wait (ulong time) { struct timespec wait = { time / 1000000000, time % 1000000000 }; while (nanosleep (& wait, null)) continue; } static float normal_r (uint colour) { return ((float) ((colour >> 24) & 0xff) / 255.0f); } static float normal_g (uint colour) { return ((float) ((colour >> 16) & 0xff) / 255.0f); } static float normal_b (uint colour) { return ((float) ((colour >> 8) & 0xff) / 255.0f); } static float normal_a (uint colour) { return ((float) ((colour >> 0) & 0xff) / 255.0f); } static uint channel_r (uint colour) { return ((colour >> 24) & 0xff); } static uint channel_g (uint colour) { return ((colour >> 16) & 0xff); } static uint channel_b (uint colour) { return ((colour >> 8) & 0xff); } static uint channel_a (uint colour) { return ((colour >> 0) & 0xff); } static uint colour_channel_reverse (uint colour) { uint r = channel_r (colour); uint g = channel_g (colour); uint b = channel_b (colour); uint a = channel_a (colour); return ((a << 24) | (b << 16) | (g << 8) | (r << 0)); } static uint colour_linear_interpolation (uint colour_a, uint colour_b, float scale) { if (scale <= 0.0f) { return (colour_a); } if (scale >= 1.0f) { return (colour_b); } uint r = (uint) ((1.0f - scale) * channel_r (colour_a) + scale * channel_r (colour_b)); uint g = (uint) ((1.0f - scale) * channel_g (colour_a) + scale * channel_g (colour_b)); uint b = (uint) ((1.0f - scale) * channel_b (colour_a) + scale * channel_b (colour_b)); uint a = (uint) ((1.0f - scale) * channel_a (colour_a) + scale * channel_a (colour_b)); return ((r << 24) | (g << 16) | (b << 8) | (a << 0)); } static void * allocate (ulong size) { char * data = null; fatal_failure (size <= 0, "allocate: Size is equal or below zero."); data = calloc (size, sizeof (* data)); fatal_failure (data == null, "allocate: Function 'calloc' returned null pointer."); return (data); } static void * reallocate (void * data, ulong size) { fatal_failure (size <= 0, "reallocate: Size is equal or below zero."); data = realloc (data, size); fatal_failure (data == null, "reallocate: Function 'realloc' returned null pointer."); return (data); } static void * deallocate (void * data) { fatal_failure (data == null, "deallocate: Data is null pointer."); free (data); return (null); } static void * record (void) { char * buffer = null; ulong offset = 0; ulong memory = 64 * 1024; buffer = reallocate (buffer, memory); do { if ((offset + 1) % memory == 0) { buffer = reallocate (buffer, ((offset + 1) / memory + 1) * memory); } buffer [offset] = '\0'; input (& buffer [offset], sizeof (* buffer)); ++offset; } while (buffer [offset - 1] != '\0'); buffer [offset - 1] = '\0'; return (buffer); } static bool character_compare_array (char character, const char * character_array) { for (ulong index = 0; character_array [index] != '\0'; ++index) { if (character == character_array [index]) { return (true); } } return (false); } static bool character_is_uppercase (char character) { return ((character >= 'A') && (character <= 'Z')); } static bool character_is_lowercase (char character) { return ((character >= 'a') && (character <= 'z')); } static bool character_is_digit (char character) { return ((character >= '0') && (character <= '9')); } static bool character_is_letter (char character) { return (((character >= 'A') && (character <= 'Z')) || ((character >= 'a') && (character <= 'z'))); } static bool character_is_blank (char character) { return ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n')); } static bool character_is_symbol (char character) { return (((character >= '!') && (character <= '/')) || ((character >= ':') && (character <= '@')) || ((character >= '[') && (character <= '`')) || ((character >= '{') && (character <= '~'))); } static bool character_is_separator (char character) { return ((character != '_') && ((character_is_blank (character) == true) || (character_is_symbol (character) == true))); } static bool character_is_identifier (char character) { return ((character == '_') || (character_is_letter (character) == true) || (character_is_digit (character) == true)); } static bool character_is_visible (char character) { return ((character >= '!') && (character <= '~')); } static char * capitalize (char * string) { fatal_failure (string == null, "capitalize: String is null pointer."); string [0] -= (character_is_lowercase (string [0]) == true) ? ' ' : '\0'; return (string); } static char * uppercase (char * string) { fatal_failure (string == null, "uppercase: String is null pointer."); for (uint index = 0; string [index] != '\0'; ++index) { string [index] += (character_is_lowercase (string [index]) == true) ? ' ' : '\0'; } return (string); } static char * lowercase (char * string) { fatal_failure (string == null, "lowercase: String is null pointer."); for (uint index = 0; string [index] != '\0'; ++index) { string [index] -= (character_is_uppercase (string [index]) == true) ? ' ' : '\0'; } return (string); } static ulong string_length (const char * string) { ulong length = 0; fatal_failure (string == null, "string_length: String is null pointer."); for (length = 0; string [length] != '\0'; ++length); return (length); } static char * string_nullify (char * string, ulong length) { fatal_failure (string == null, "string_nullify: String is null pointer."); fatal_failure (length <= 0, "string_nullify: Length is equal or below zero."); for (ulong index = 0; index < length; ++index) { string [index] = '\0'; } return (string); } static char * string_reverse_limit (char * string, ulong limit) { fatal_failure (string == null, "string_reverse_limit: String is null pointer."); fatal_failure (limit <= 0, "string_reverse_limit: Limit is equal or below zero."); for (ulong index = 0; index < limit / 2; ++index) { char temporary = string [index]; string [index] = string [limit - 1 - index]; string [limit - 1 - index] = temporary; } return (string); } static char * string_reverse (char * string) { return (string_reverse_limit (string, string_length (string))); } static bool string_compare_limit (const char * string_a, const char * string_b, ulong limit) { fatal_failure (string_a == null, "string_compare_limit: First source string is null pointer."); fatal_failure (string_b == null, "string_compare_limit: Second source string is null pointer."); fatal_failure (limit <= 0, "string_compare_limit: Limit is equal or below zero."); for (ulong index = 0; index < limit; ++index) { if (string_a [index] != string_b [index]) { return (false); } } return (true); } static bool string_compare (const char * string_a, const char * string_b) { return (string_compare_limit (string_a, string_b, string_length (string_a) + 1)); } static char * string_copy_limit (char * destination, const char * source, ulong limit) { fatal_failure (destination == null, "string_copy_limit: Destination string is null pointer."); fatal_failure (source == null, "string_copy_limit: Source string is null pointer."); fatal_failure (limit <= 0, "string_copy_limit: Limit is equal or below zero."); for (ulong index = 0; index < limit; ++index) { destination [index] = source [index]; } return (destination); } static char * string_copy (char * destination, const char * source) { return (string_copy_limit (destination, source, string_length (source) + 1)); } static char * string_concatenate_limit (char * destination, const char * source, ulong limit) { ulong offset = string_length (destination); fatal_failure (destination == null, "string_concatenate_limit: Destination string is null pointer."); fatal_failure (source == null, "string_concatenate_limit: Source string is null pointer."); fatal_failure (limit <= 0, "string_concatenate_limit: Limit is equal or below zero."); for (ulong index = 0; index < limit; ++index) { destination [offset + index] = source [index]; } return (destination); } static char * string_concatenate (char * destination, const char * source) { return (string_concatenate_limit (destination, source, string_length (source) + 1)); } static char * string_duplicate (const char * string) { char * duplicate = null; duplicate = allocate ((string_length (string) + 1) * sizeof (* duplicate)); string_copy (duplicate, string); return (duplicate); } static char * string_duplicate_limit (const char * string, uint limit) { char * duplicate = null; duplicate = allocate ((limit + 1) * sizeof (* duplicate)); string_copy_limit (duplicate, string, limit); return (duplicate); } static char * string_align_left (char * string, ulong amount, char character) { ulong length = string_length (string); for (ulong offset = length; offset < amount; ++offset) { string [offset] = character; } string [amount] = '\0'; return (string); } static void memory_nullify (void * memory, ulong size) { char * cast = (char *) memory; fatal_failure (memory == null, "memory_nullify: Memory is null pointer."); for (ulong offset = 0; offset < size; ++offset) { cast [offset] = (char) 0; } } static int memory_compare (void * memory_0, const void * memory_1, ulong size) { char * cast_0 = ( char *) memory_0; const char * cast_1 = (const char *) memory_1; fatal_failure (memory_0 == null, "memory_compare: Memory is null pointer."); fatal_failure (memory_1 == null, "memory_compare: Source is null pointer."); for (ulong offset = 0; offset < size; ++offset) { if (cast_0 [offset] != cast_1 [offset]) { return (false); } } return (true); } static void memory_copy (void * destination, const void * source, ulong size) { char * cast_0 = ( char *) destination; const char * cast_1 = (const char *) source; fatal_failure (destination == null, "memory_copy: Destination is null pointer."); fatal_failure (source == null, "memory_copy: Source is null pointer."); for (ulong offset = 0; offset < size; ++offset) { cast_0 [offset] = cast_1 [offset]; } } static char * string_remove_extension (char * string) { ulong length = string_length (string); for (--length; string [length] != '.'; --length); string [length] = '\0'; return (string); } static void echo_clear (void) { echo ("\033[2J\033[H"); } static void echo_colour (colour_enumeration colour, effect_enumeration effect) { char format [8] = "\033[ ;3 m"; format [2] = (char) (effect % effect_count) + '0'; format [5] = (char) (colour % colour_count) + '0'; echo (format); } static void echo_cancel (void) { echo ("\033[0m"); } static void show_cursor (bool show) { if (show == true) { echo ("\033[?25h"); } else { echo ("\033[?25l"); } } static int file_open (const char * path, int mode) { fatal_failure (path == null, "file_open: File path is null pointer."); return (open (path, mode, 0777)); } static int file_close (int file) { fatal_failure (file == -1, "file_close: Invalid file descriptor."); close (file); return (-1); } static void file_read (int file, void * data, ulong size) { fatal_failure (file <= -1, "file_read: File descriptor is closed or invalid."); fatal_failure (data == null, "file_read: Data is null pointer."); fatal_failure (size == 0, "file_read: Size is zero."); read (file, data, size); } static void file_write (int file, const void * data, ulong size) { fatal_failure (file <= -1, "file_write: File descriptor is closed or invalid."); fatal_failure (data == null, "file_write: Data is null pointer."); fatal_failure (size == 0, "file_write: Size is zero."); write (file, data, size); } static void file_echo (int file, const char * data) { file_write (file, data, string_length (data)); } static ulong file_seek (int file, int whence) { fatal_failure (file == -1, "file_seek: Invalid file descriptor."); return ((ulong) lseek (file, 0, whence)); } static ulong file_size (const char * path) { struct stat data = { 0 }; fatal_failure (path == null, "file_size: File path is null pointer."); lstat (path, & data); return ((ulong) data.st_size); } static file_type_enumeration file_type (const char * path) { const char * extensions [file_type_count] = { ".c", ".h", ".adb", ".ads", ".cpp", ".hpp", ".f90", ".mod", ".pas", ".d", ".go", ".jai", ".asm", ".eax", ".gas", ".fasm", ".hs", ".el", ".cfg", ".lua", ".sh", ".py", ".tcl", ".4th", ".txt", ".md", ".html", ".glsl", ".x", ".xhla", ".xs", ".xd", ".xiri", ".xofya", ".xienna", ".xenka", ".xiyagi", ".xoule", ".xikoku", ".xdo", ".png", ".jxl", ".jpg", ".tga", ".wav", ".ogg", ".flac", ".mp3", ".obj", ".iqm", ".md5", ".ply", ".o", ".spv" }; fatal_failure (path == null, "file_type: File path is null pointer."); for (; * path != '.'; ++path); for (file_type_enumeration type = 0; type != file_type_count; ++type) { if (string_compare (path, extensions [type])) { return (type); } } return (~ 0u); } static bool file_exists (const char * path) { fatal_failure (path == null, "file_record: File path is null pointer."); return ((access (path, F_OK) == 0) ? true : false); } static void file_remove (const char * path) { unlink (path); } static void * file_record (const char * path) { int file = -1; ulong size = 0; char * data = null; fatal_failure (path == null, "file_record: File path is null pointer."); file = file_open (path, file_flag_read); size = file_size (path); data = allocate (size); file_read (file, data, size); file = file_close (file); return (data); } static char * file_import (const char * path) { int file = -1; ulong size = 0; char * data = null; fatal_failure (path == null, "file_import: File path is null pointer."); file = file_open (path, file_flag_edit); size = file_size (path) + 1; data = allocate (size); file_read (file, data, size - 1); data [size - 1] = '\0'; file = file_close (file); return (data); } static void file_export (const char * path, const char * data) { int file = -1; fatal_failure (path == null, "file_export: File path is null pointer."); fatal_failure (data == null, "file_export: Data is null pointer."); file = file_open (path, file_flag_write | file_flag_create | file_flag_truncate); file_write (file, data, string_length (data)); file = file_close (file); } static void * folder_open (const char * path) { DIR * folder = null; fatal_failure (path == null, "folder_open: Folder path is null pointer."); folder = opendir (path); return ((void *) folder); } static char * folder_read (void * handle) { struct dirent * file = null; DIR * folder = (DIR *) handle; fatal_failure (handle == null, "folder_read: Folder handle is null pointer."); file = readdir (folder); if (file == null) { return (null); } else { return (file->d_name); } } static void * folder_close (void * handle) { DIR * folder = (DIR *) handle; fatal_failure (handle == null, "folder_read: Folder handle is null pointer."); closedir (folder); return (null); } static char * * folder_create_path_list (const char * folder, uint * path_count, bool sort) { void * handle = null; char * * path_array = 0; (void) sort; fatal_failure (folder == null, "folder_create_path_list: Folder handle is null pointer."); fatal_failure (path_count == null, "folder_create_path_list: Path count address is null pointer."); handle = folder_open (folder); for (char * path = folder_read (handle); path != null; path = folder_read (handle)) { if (path [0] != '.') { (* path_count) += 1; path_array = reallocate (path_array, (* path_count) * sizeof (* path_array)); path_array [(* path_count) - 1] = allocate ((string_length (path) + 1) * sizeof (* * path_array)); string_copy (path_array [(* path_count) - 1], path); } } handle = folder_close (handle); return (path_array); } static char * * folder_remove_path_list (char * * path_array, uint path_count) { for (uint index = 0; index < path_count; ++index) { path_array [index] = deallocate (path_array [index]); } return (deallocate (path_array)); } static char * configuration_format (const char * path) { static char buffer [512] = ""; string_copy (buffer, getenv ("HOME")); string_concatenate (buffer, "/.config/xolatile/"); string_concatenate (buffer, path); return (buffer); } static bool configuration_exists (const char * path) { return (file_exists (configuration_format (path))); } static void configuration_remove (const char * path) { file_remove (configuration_format (path)); } static char * configuration_import (const char * path) { return (file_import (configuration_format (path))); } static void configuration_export (const char * path, const char * data) { file_export (configuration_format (path), data); } static bool argument_compare (const char * argument, const char * short_option, const char * long_option) { return ((string_compare (argument, short_option) == true) || (string_compare (argument, long_option) == true)); } static uint string_full_width (const char * string, uint tab_width) { uint width = 0; uint count = 0; do { if (* string == '\t') { count += tab_width; } else if (* string == '\n') { width = (++count > width) ? count : width; count = 0; } else { ++count; } } while (* (++string) != '\0'); return (width - 1); } static uint string_full_height (const char * string) { uint height = 0; do { if (* string == '\n') { ++height; } } while (* (++string) != '\0'); return (height + 1); } static uint string_limit_to_number (const char * string, uint limit) { uint number = 0; for (uint index = 0; (string [index] != '\0') && (index < limit); ++index) { number *= 10; number += (uint) (string [index] - '0'); } return (number); } static uint string_to_number (const char * string) { return (string_limit_to_number (string, string_length (string))); } static char * number_to_string (int number) { static char string [34] = ""; uint index = 0; bool sign = false; string_nullify (string, sizeof (string)); if (number == 0) { string [0] = '0'; string [1] = '\0'; return (string); } if (number < 0) { number *= -1; sign = true; } else { sign = false; } for (index = 0; (number != 0) && (index < (uint) sizeof (string) - 1); ++index) { string [index] = (char) (number % 10) + '0'; number /= 10; } if (sign == true) { string [index] = '-'; ++index; } string [index] = '\0'; string_reverse (string); return (string); } static char * format_to_string (int number, bool sign, uint base, ulong amount, char character) { static char string [36]; int i; string_nullify (string, sizeof (string)); if (number == 0) { string [0] = '0'; string [1] = '\0'; string_align_left (string, amount, character); return (string); } if (number < 0) { number *= -1; } for (i = (string [0] == '-'); number != 0; ++i) { string [i] = "0123456789ABCDEF" [number % base]; number /= base; } if (sign == true) { string [i] = '-'; ++i; } string [i] = '\0'; string_reverse (string); string_align_left (string, amount, character); return (string); } static char * format (const char * base, ...) { static char string [1024]; va_list list; string_nullify (string, 1024); va_start (list, base); for (; * base != character_null; ++base) { switch (* base) { case ('%'): { ++base; switch (* base) { case ('%'): string_concatenate (string, "%"); break; case ('i'): string_concatenate (string, number_to_string (va_arg (list, int))); break; case ('s'): string_concatenate (string, va_arg (list, char *)); break; default: string_concatenate (string, "?"); break; } } break; default: { string_concatenate_limit (string, base, 1); } break; } } va_end (list); return (string); } static void print (const char * format, ...) { va_list list; va_start (list, format); for (; * format != character_null; ++format) { switch (* format) { case ('%'): { ++format; switch (* format) { case ('%'): { output ("%", 1); } break; case ('i'): { char * string = number_to_string (va_arg (list, int)); output (string, string_length (string)); } break; case ('t'): { int toggle = (va_arg (list, int)); echo_colour ((toggle == true) ? colour_green : colour_red, effect_normal); output ((toggle == true) ? "+" : "-", 1); echo_cancel (); } break; case ('b'): { int boolean = (va_arg (list, int)); output ((boolean == true) ? "true" : "false", (boolean == true) ? 4 : 5); } break; case ('c'): { char character = (char) va_arg (list, int); output (& character, 1); } break; case ('s'): { char * string = va_arg (list, char *); output (string, string_length (string)); } break; default: { output ("?", 1); } break; } } break; case ('/'): { ++format; switch (* format) { case ('/'): echo ("/"); break; case ('s'): echo ("[\x1b[1;32mSuccess\x1b[0m]"); break; case ('f'): echo ("[\x1b[1;31mFailure\x1b[0m]"); break; case ('w'): echo ("[\x1b[1;33mWarning\x1b[0m]"); break; case ('c'): echo ("[\x1b[1;30mComment\x1b[0m]"); break; case ('A'): echo ("\x1b[0m"); break; case ('B'): echo ("\x1b[1m"); break; case ('C'): echo ("\x1b[2m"); break; case ('D'): echo ("\x1b[3m"); break; case ('E'): echo ("\x1b[4m"); break; case ('F'): echo ("\x1b[5m"); break; case ('G'): echo ("\x1b[6m"); break; case ('H'): echo ("\x1b[7m"); break; case ('0'): echo ("\x1b[30m"); break; case ('1'): echo ("\x1b[31m"); break; case ('2'): echo ("\x1b[32m"); break; case ('3'): echo ("\x1b[33m"); break; case ('4'): echo ("\x1b[34m"); break; case ('5'): echo ("\x1b[35m"); break; case ('6'): echo ("\x1b[36m"); break; case ('7'): echo ("\x1b[37m"); break; case ('-'): echo ("\x1b[0m"); break; default: echo ("?"); break; } } break; default: { output (format, 1); } break; } } va_end (list); } static void uint_exchange (uint * a, uint * b) { uint c = * a; * a = * b; * b = c; } static void float_exchange (float * a, float * b) { float c = * a; * a = * b; * b = c; } #ifdef use_mathematics #include #define pi (3.14159265f) static float sign (float x) { return ((x > 0.0f) ? +1.0f : -1.0f); } static float square_root (float x) { return (sqrtf (x)); } static float cube_root (float x) { return (cbrtf (x)); } static float sine (float x) { return (sinf (x)); } static float cosine (float x) { return (cosf (x)); } static float tangent (float x) { return (tanf (x)); } static float arc_sine (float x) { return (asinf (x)); } static float arc_cosine (float x) { return (acosf (x)); } static float arc_tangent (float x) { return (atanf (x)); } static float cosecant (float x) { return (1.0f / sinf (x)); } static float secant (float x) { return (1.0f / cosf (x)); } static float cotangent (float x) { return (1.0f / tanf (x)); } #endif