/// _ _ _ /// | | | | | | /// __ _| |_ __ _ _ __ __| | __ _ _ __ __| | /// \ \/ / __/ _` | '_ \ / _` |/ _` | '__/ _` | /// > <| || (_| | | | | (_| | (_| | | | (_| | /// /_/\_\\__\__,_|_| |_|\__,_|\__,_|_| \__,_| /// /// 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 char * cursor_name [cursor_count] = { "---", "Left button", "Middle button", "Right button", "Scroll up", "Scroll down" }; static 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 (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, 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 (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, 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 (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 (char * string_a, 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 (char * string_a, char * string_b) { return (string_compare_limit (string_a, string_b, string_length (string_a) + 1)); } static char * string_copy_limit (char * destination, 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, char * source) { return (string_copy_limit (destination, source, string_length (source) + 1)); } static char * string_concatenate_limit (char * destination, 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, char * source) { return (string_concatenate_limit (destination, source, string_length (source) + 1)); } static char * string_duplicate (char * string) { char * duplicate = null; duplicate = allocate ((string_length (string) + 1) * sizeof (* duplicate)); string_copy (duplicate, string); return (duplicate); } static char * string_duplicate_limit (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, void * memory_1, ulong size) { char * cast_0 = ( char *) memory_0; char * cast_1 = (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, void * source, ulong size) { char * cast_0 = ( char *) destination; char * cast_1 = (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 (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, 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, 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 (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 (char * path) { /// SHIT BREAKS ON "./THIS/THAT.EXT"... 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 (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 (char * path) { unlink (path); } static void * file_record (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 (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 (char * path, 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 (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 (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 (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 (char * path) { return (file_exists (configuration_format (path))); } static void configuration_remove (char * path) { file_remove (configuration_format (path)); } static char * configuration_import (char * path) { return (file_import (configuration_format (path))); } static void configuration_export (char * path, char * data) { file_export (configuration_format (path), data); } static bool argument_compare (char * argument, char * short_option, char * long_option) { return ((string_compare (argument, short_option) == true) || (string_compare (argument, long_option) == true)); } static uint string_full_width (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 (char * string) { uint height = 0; do { if (* string == '\n') { ++height; } } while (* (++string) != '\0'); return (height + 1); } static uint string_limit_to_number (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 (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 (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 (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 ('f'): { float number = (float) va_arg (list, double); char * upper = number_to_string ((int) number); char * lower = number_to_string ((int) (number * 1000.0f) % 1000); output (upper, string_length (upper)); output (".", 1); output (lower, string_length (lower)); } 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 binary_sign (uint x) { return ((x > 0) ? + 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