aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md11
-rw-r--r--icon.xcfbin195160 -> 56661 bytes
-rw-r--r--modules/README.md7
-rw-r--r--unused.c261
-rw-r--r--unused.jai421
5 files changed, 11 insertions, 689 deletions
diff --git a/README.md b/README.md
index d0c9502..43226f8 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,10 @@ Task Time Tracker
A tool to keep track of the time spent on tasks.
+Source: <https://source.gudinoff.com/dam/task-time-tracker>
+Contact: <https://www.gudinoff.com/dam/contact.html>
+
+
# Why use it?
Why not? Besides, you'll be able to create, duplicate, move, rename,
@@ -112,7 +116,7 @@ and that’s what I did.
After surfing an uncountable number of websites and manuals about linux,
terminals, escape codes, and whatnot, I ended up creating
-[TUI](https://github.com/gudinoff/jai-modules), a simple terminal user
+[TUI](https://source.gudinoff.com/dam/jai-modules), a simple terminal user
interface module that provides basic functionalities similar to the
[ncurses library](https://en.wikipedia.org/wiki/Ncurses), written in Jai
to allow portability between OSs.
@@ -125,6 +129,5 @@ spread its wings.
# License
-Licensed under GPL-3.0-or-later.
-
-SPDX-License-Identifier: GPL-3.0-or-later
+Licensed under GPL-3.0-or-later.
+SPDX-License-Identifier: GPL-3.0-or-later.
diff --git a/icon.xcf b/icon.xcf
index 4075db2..351a962 100644
--- a/icon.xcf
+++ b/icon.xcf
Binary files differ
diff --git a/modules/README.md b/modules/README.md
index 13179e6..0f8c159 100644
--- a/modules/README.md
+++ b/modules/README.md
@@ -3,13 +3,13 @@ jai-modules
Modules for the language being developed by Thekla, Inc.
-Available at https://github.com/gudinoff/jai-modules
+Available at <https://source.gudinoff.com>
# Saturation
This module provides basic integer [saturation arithmetic](https://en.wikipedia.org/wiki/Saturation_arithmetic) procedures: `add`, `sub`, `mul`, and `div`.
-These procedures accept any of the built-in integer types and adjust the output accordingly, e.g., adding an `u8` with an `s16` results in an `s16`;
-All procedures return a flag signaling if the result is saturated and, additionally, the division procedure returns the remainder;
+These procedures accept any of the built-in integer types and adjust the output accordingly, e.g., adding an `u8` with an `s16` results in an `s16`.
+All procedures return a flag signaling if the result is saturated and, additionally, the division procedure returns the remainder.
Branch-free procedures are included for the x64 architecture. These may be used by setting the `PREFER_BRANCH_FREE_CODE` module argument, or by setting `prefer_branch_free_code` on each function call. These should speed things up, specially when using signed values. Some benchmarks are included on the tests file.
# TUI
@@ -18,6 +18,7 @@ A simple terminal user interface module that provides basic functionalities simi
Usefull for creating simple terminal-based apps that require user input.
View `snake.jai` for an example.
It has been tested on the following terminal emulators:
+
- [GNOME Terminal](https://en.wikipedia.org/wiki/GNOME_Terminal)
- [kitty](https://en.wikipedia.org/wiki/Kitty_(terminal_emulator))
- [Konsole](https://en.wikipedia.org/wiki/Konsole)
diff --git a/unused.c b/unused.c
deleted file mode 100644
index 48d23c7..0000000
--- a/unused.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
-// Alternative code to print a task row.
-
- ////////////////////////------------------
- total_time = 0;
- char t0[10], t1[10], t2[10], t3[10], t4[10], t5[10], t6[10], t7[10];
- for (int idx = 0; idx < NUM_WEEK_DAYS; idx++) {
- total_time = add_int64(total_time, task->times[idx]);
- }
- snprintf(string_buffer, size_x - 2 + 1, "%-*.*s %*s %*s %*s %*s %*s %*s %*s %*s",
- layout->columns[L_TITLE_IDX].width,
- layout->columns[L_TITLE_IDX].width,
- task->name,
-
- layout->columns[1].width,
- print_time_5cc(t0, task->times[(0 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[2].width,
- print_time_5cc(t1, task->times[(1 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[3].width,
- print_time_5cc(t2, task->times[(2 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[4].width,
- print_time_5cc(t3, task->times[(3 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[5].width,
- print_time_5cc(t4, task->times[(4 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[6].width,
- print_time_5cc(t5, task->times[(5 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[7].width,
- print_time_5cc(t6, task->times[(6 + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS], layout->columns[1].width + 1),
- layout->columns[L_TOTAL_IDX].width,
- print_time_5cc(t1, total_time, layout->columns[L_TOTAL_IDX].width + 1)
- );
- mvaddnstr(y, 1, string_buffer, size_x - 2);
- ////////////////////////------------------
-
- */
-
-
-// Prints time into string using 5 characters centered on space.
-// The string buffer should be able to store space UTF8 characters plus '\0'.
-char *sprint_time5_utf8(char *string, intmax_t time, int space) {
- const int TIME_CHARS = 5;
- assert(space >= TIME_CHARS);
-
- int buffer_space = space * 4 + 1; // Each that UTF8 char can have 4 bytes.
- int left_padding = (space - TIME_CHARS) / 2;
- int right_padding = space - TIME_CHARS - left_padding;
-
- if (time < 0) {
- snprintf(string, buffer_space, "%*s - %*s", left_padding, "", right_padding, "");
- }
- else if (time == 0) {
- snprintf(string, buffer_space, "%*s 0 %*s", left_padding, "", right_padding, "");
- }
- else if (time < SECONDS_IN_MINUTE) {
- snprintf(string, buffer_space, "%*s%3jds %*s", left_padding, "", time, right_padding, "");
- }
- else if (time < (intmax_t)100 * SECONDS_IN_HOUR) {
- intmax_t hours = (double)time / (double)SECONDS_IN_HOUR;
- intmax_t minutes = (time - (hours * SECONDS_IN_HOUR) ) / SECONDS_IN_MINUTE;
- snprintf(string, buffer_space, "%*s%02jd:%02jd%*s", left_padding, "", hours, minutes, right_padding, "");
- }
- else if (time < (intmax_t)(9999.5 * SECONDS_IN_DAY)) {
- double value = (double)time / (double)SECONDS_IN_DAY;
- int decimals =
- time >= 99.95 * SECONDS_IN_DAY ? 0 :
- time >= 9.995 * SECONDS_IN_DAY ? 1 :
- 2;
- snprintf(string, buffer_space, "%*s%4.*fd%*s", left_padding, "", decimals, value, right_padding, "");
- }
- else if (time < (intmax_t)(9999.5 * SECONDS_IN_YEAR)) {
- double value = (double)time / (double)SECONDS_IN_YEAR;
- int decimals =
- time >= 99.95 * SECONDS_IN_YEAR ? 0 :
- time >= 9.995 * SECONDS_IN_YEAR ? 1 :
- 2;
- snprintf(string, buffer_space, "%*s%4.*fy%*s", left_padding, "", decimals, value, right_padding, "");
- }
- else {
- snprintf(string, buffer_space, "%*s ∞ %*s", left_padding, "", right_padding, "");
- }
-
- return string;
-}
-
-
-// Writes only the database core structure and the provided task if not null.
-// Returns success.
-bool store_database_partial(const database_st *db, const task_st *task, const char *path) {
- return store_database(db, path);
- assert(db != NULL);
- assert(path != NULL);
-
- // Open file.
- FILE *file = fopen(path, "r+b");
- if (file == NULL) {
- fprintf(stderr, "Failed to open file '%s' while partially storing database: %s.\n", path, strerror(errno));
- return false;
- }
-
- fseek(file, DB_FILE_SIGN_LENGTH, SEEK_SET);
- fwrite(db, SIZEOF_DATABASE_ST, 1, file);
-
- if (task != NULL) {
- assert(task >= db->tasks && task < &db->tasks[db->count]);
- ptrdiff_t offset = task - db->tasks;
- fseek(file, offset * SIZEOF_TASK_ST, SEEK_CUR);
- fwrite(task, SIZEOF_TASK_ST, 1, file);
- }
-
- fclose(file);
- return true;
-}
-
-// Returns the number of characters in a string using UTF8 encoding.
-size_t length_utf8(char *string) {
- size_t size = 0;
- char *ptr = string;
- while(*ptr != '\0') {
- if ((*ptr & 0xC0) != 0x80) {
- size++;
- }
- ptr++;
- }
- return size;
-}
-
-
-
-// Adds task to database. If necessary, expands database capacity.
-// Returns success.
-bool add_task(database_t* db, const task_t* task) {
- assert(db != NULL);
- assert(task != NULL);
-
- if (db->count == UINT32_MAX) {
- fprintf(stderr, "Database reached maximum capacity, discarding task '%s'.\n", task->name);
- return false;
- }
-
- // If necessary, expand database capacity.
- uint32_t current_capacity = db->capacity;
- if((db->count + 1) > current_capacity) {
- uint32_t new_capacity = current_capacity == 0 ? 2 :
- current_capacity >= UINT32_MAX >> 2 ? UINT32_MAX :
- current_capacity << 1;
-
- task_t* new_tasks = realloc(db->tasks, new_capacity * SIZEOF_TASK_T);
- if (new_tasks == NULL) {
- fprintf(stderr, "Failed to expand database, discarding task '%s'.\n", task->name);
- return false;
- }
- db->capacity = new_capacity;
- db->tasks = new_tasks;
- }
-
- // Store new task.
- memcpy(&(db->tasks[db->count]), task, SIZEOF_TASK_T);
- db->count++;
-
- return true;
-}
-
-// Removes task by index from database. If possible, shrinks database capacity.
-// Returns success.
-bool remove_task(database_t* db, uint32_t index) {
- assert(db != NULL);
- assert(index < db->count);
-
- if (index >= db->count) {
- fprintf(stderr, "Failed to remove out-of-bounds index '%" PRIu32 "'.", index);
- return false;
- }
-
- // Move tasks after the index position to their new positions.
- memmove(&db->tasks[index], &db->tasks[index+1], (db->count - index - 1) * SIZEOF_TASK_T);
- db->count--;
-
- // If possible, shrink database capacity.
- size_t current_capacity = db->capacity;
- if (db->count <= (current_capacity >> 2)) {
- ptrdiff_t selected_task_offset = db->tasks - db->active_task;
- size_t new_capacity = current_capacity >> 1;
- task_t* new_tasks = realloc(db->tasks, new_capacity * SIZEOF_TASK_T);
- if (new_tasks == NULL) {
- fprintf(stderr, "Failed to shrink database.\n");
- return false;
- }
- db->capacity = new_capacity;
- db->tasks = new_tasks;
- db->active_task = db->tasks + selected_task_offset;
- // Validate selected_task (may now be above count.
- }
-
- return true;
-}
-
-uint32_t CRC32(const uint8_t data[], size_t data_length) {
-
- static const uint32_t crc32_table[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
- };
-
- uint32_t crc32 = 0xFFFFFFFFu;
-
- for (size_t i = 0; i < data_length; i++) {
- const uint32_t lookupIndex = (crc32 ^ data[i]) & 0xff;
- crc32 = (crc32 >> 8) ^ crc32_table[lookupIndex];
- }
-
- // Finalize the CRC-32 value by inverting all the bits
- crc32 ^= 0xFFFFFFFFu;
- return crc32;
-}
-
-uint32_t hash_string(const char* string) {
- size_t data_length = strlen(string);
- uint8_t* data = (uint8_t*)string;
- return CRC32(data, data_length);
-}
diff --git a/unused.jai b/unused.jai
deleted file mode 100644
index da8b41d..0000000
--- a/unused.jai
+++ /dev/null
@@ -1,421 +0,0 @@
-auto_release_temp(); // automatically release temporary memory.
-print(">%<", S64_MIN + delta, to_standard_error = true);
-print_to_builder(*builder, "Average % us (% / % bytes) ---------", dbg_average/1000, context.temporary_storage.total_bytes_occupied, context.temporary_storage.high_water_mark); // DEBUG
-print("temp [% .. % .. %] \n", context.temporary_storage.data, get_temporary_storage_mark(), context.temporary_storage.data + context.temporary_storage.size-1);
-
-
-// MEASURE PERFORMANCE
-{
- dbg_average := 0; // DEBUG
- dbg_count := 0; // DEBUG
-
- #import "Basic";
-
- // Cumulative average: CA_n+1 = (x_n+1 + n*CA_n ) / (n + 1)
- start := current_time_monotonic(); // DEBUG
- // ...code to be measured...
- stop := current_time_monotonic(); // DEBUG
- dbg_sample := to_nanoseconds(stop-start); // DEBUG
- dbg_average = (dbg_sample + dbg_count * dbg_average) / (dbg_count + 1); // DEBUG
- dbg_count += 1; // DEBUG
- print("Average % ns.\n", dbg_average); // DEBUG
-}
-
-// Memory allocator debugging.
-print_owner_allocator :: (tag: string, memory: *void) {
- owner := "unkown";
-
- if true == xx context.allocator.proc(.IS_THIS_YOURS, 0, 0, memory, null) then owner = "default";
- else if true == xx temp.proc(.IS_THIS_YOURS, 0, 0, memory, null) then owner = "temp";
-
- print("'%' belongs to '%'\n", tag, owner);
-}
-
-// ttt's database debugging.
-print_database :: (db: Database) {
- for db.tasks {
- print("% | % : % : % : % : % : % : %\n", cast(string)it.name,
- it.times[0],
- it.times[1],
- it.times[2],
- it.times[3],
- it.times[4],
- it.times[5],
- it.times[6]
- );
- }
-}
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-DB_FILE_SIGN_STR :: "TTT:B:02";
-
-// Stores data from database into binary file.
-// Returns success.
-store_database :: (db: Database, path: string) -> success: bool #must {
- assert(xx path, ASSERT_NOT_EMPTY, "path");
-
- // Open file.
- file, open_success := file_open(path, for_writing = true);
- if open_success == false return false;
- defer file_close(*file);
-
- file_write(*file, DB_FILE_SIGN_STR);
- file_write(*file, *db, size_of(Database));
- file_write(*file, db.tasks.data, size_of(Task) * db.tasks.count);
-
- return true;
-}
-
-// Loads data from binary file into database.
-// Returns success.
-load_database :: (db: *Database, path: string) -> success: bool #must {
- assert(db != null, ASSERT_NOT_NULL, "db");
- assert(xx path, ASSERT_NOT_EMPTY, "path");
-
- // Open file.
- file, open_success := file_open(path);
- if open_success == false then return false;
- defer file_close(*file);
-
- // Validate file signature.
- file_signature: [DB_FILE_SIGN_STR.count] u8;
- read_success := file_read(file, *file_signature, DB_FILE_SIGN_STR.count);
- if read_success == false log_error("Failed to read file signature.");
- if cast(string)file_signature != DB_FILE_SIGN_STR {
- log_error("Invalid file signature while loading database.");
- return false;
- }
-
- // Read database structure.
- read_success = file_read(file, db, size_of(Database));
- if read_success == false {
- log_error("Failed to read database info.");
- return false;
- }
-
- // Reserve database capacity for tasks.
- tasks_count := db.tasks.count;
- Initialize(*db.tasks); // Cleanup whatever was read from file.
- array_reserve(*db.tasks, tasks_count);
-
- // Read database tasks.
- file_read(file, db.tasks.data, size_of(Task) * tasks_count);
- db.tasks.count = tasks_count;
-
- // Make sure we are reading all the file.
- buffer: u8;
- success, bytes := file_read(file, *buffer, 1);
- if bytes > 0 {
- log_error("Unexpected content found at the end of file '%'.", path);
- return false;
- }
-
- return true;
-}
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-
-// Average cumulative calculation.
-average: float64 = 0;
-counter: float64 = 0;
-t0 := current_time_monotonic();
-t1 := current_time_monotonic();
-set_cursor_position(2, 47);
-sample := cast(float64)to_nanoseconds(t1-t0)/1000;
-average = (sample + counter * average) / (counter + 1);
-counter += 1;
-print(">%us<", average);
-
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-// Implementation of tcsetattr, tcgetattr, and tcflush using only 'ioctl' which is provided by jai.
-
-#if USE_LIBC {
-
- libc :: #system_library "libc";
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html
- tcsetattr :: (fd: s32, optional_actions: s32, termios_p : *Terminal_IO_Mode) -> s32 #foreign libc;
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html
- tcgetattr :: (fd: s32, termios_p: *Terminal_IO_Mode) -> s32 #foreign libc;
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcflush.c.html
- tcflush :: (fd: s32, queue_selector: s32) -> s32 #foreign libc;
-}
-else {
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html
- tcsetattr :: (fd: s32, optional_actions: s32, termios_p : *Terminal_IO_Mode) -> s32 {
-
- #if OS == .LINUX {
- TCSETS :: 0x5402;
- TCSETSW :: 0x5403;
- TCSETSF :: 0x5404;
- tcflag_t :: u32;
- cc_t :: u8;
- __KERNEL_NCCS :: 19;
- __kernel_termios :: struct {
- c_iflag : tcflag_t; // input mode flags
- c_oflag : tcflag_t; // output mode flags
- c_cflag : tcflag_t; // control mode flags
- c_lflag : tcflag_t; // local mode flags
- c_line : cc_t; // line discipline
- c_cc : [__KERNEL_NCCS]cc_t; // control characters
- };
-
- k_termios: __kernel_termios;
- cmd: u64;
- if optional_actions == {
- case xx Optional_Actions.TCSANOW;
- cmd = TCSETS;
-
- case xx Optional_Actions.TCSADRAIN;
- cmd = TCSETSW;
-
- case xx Optional_Actions.TCSAFLUSH;
- cmd = TCSETSF;
-
- case;
- return EINVAL;
- }
- // k_termios.c_iflag = termios_p.c_iflag & ~IBAUD0;
- k_termios.c_iflag = xx termios_p.c_iflag;
- k_termios.c_oflag = xx termios_p.c_oflag;
- k_termios.c_cflag = xx termios_p.c_cflag;
- k_termios.c_lflag = xx termios_p.c_lflag;
- k_termios.c_line = xx termios_p.c_line;
- // #if _HAVE_C_ISPEED && _HAVE_STRUCT_TERMIOS_C_ISPEED
- // k_termios.c_ispeed = termios_p->c_ispeed;
- // #endif
- // #if _HAVE_C_OSPEED && _HAVE_STRUCT_TERMIOS_C_OSPEED
- // k_termios.c_ospeed = termios_p->c_ospeed;
- // #endif
- memcpy(*k_termios.c_cc[0], *termios_p.c_cc[0], __KERNEL_NCCS * 1);//size_of(cc_t));
- return ioctl(fd, cmd, *k_termios);
- }
- #if OS == .MACOS {
- // return __ioctl (fd, TIOCSETAF, termios_p);
- #assert(false, "NOT IMPLEMENTED");
- }
- return 0;
- }
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html
- tcgetattr :: (fd: s32, termios_p: *Terminal_IO_Mode) -> s32 {
- TCSETS :: 0x5402;
- TCSETSW :: 0x5403;
- TCSETSF :: 0x5404;
- tcflag_t :: u32;
- cc_t :: u8;
- __KERNEL_NCCS :: 19;
- __kernel_termios :: struct {
- c_iflag : tcflag_t; // input mode flags
- c_oflag : tcflag_t; // output mode flags
- c_cflag : tcflag_t; // control mode flags
- c_lflag : tcflag_t; // local mode flags
- c_line : cc_t; // line discipline
- c_cc : [__KERNEL_NCCS]cc_t; // control characters
- };
-
-
- // int
- // __tcgetattr (int fd, struct termios *termios_p)
- // {
- // struct __kernel_termios k_termios;
- k_termios: __kernel_termios;
- retval: int;
- retval = ioctl(fd, TCGETS, *k_termios);
- if retval == 0 {
- termios_p.c_iflag = xx k_termios.c_iflag;
- termios_p.c_oflag = xx k_termios.c_oflag;
- termios_p.c_cflag = xx k_termios.c_cflag;
- termios_p.c_lflag = xx k_termios.c_lflag;
- termios_p.c_line = xx k_termios.c_line;
- // #if _HAVE_STRUCT_TERMIOS_C_ISPEED
- // # if _HAVE_C_ISPEED
- // termios_p->c_ispeed = k_termios.c_ispeed;
- // # else
- // termios_p->c_ispeed = k_termios.c_cflag & (CBAUD | CBAUDEX);
- // # endif
- // #endif
- // #if _HAVE_STRUCT_TERMIOS_C_OSPEED
- // # if _HAVE_C_OSPEED
- // termios_p->c_ospeed = k_termios.c_ospeed;
- // # else
- // termios_p->c_ospeed = k_termios.c_cflag & (CBAUD | CBAUDEX);
- // # endif
- // #endif
- size_of_cc_t := __KERNEL_NCCS * 1;
- memcpy(*termios_p.c_cc[0], *k_termios.c_cc[0], size_of_cc_t);
- // memset(*termios_p.c_cc[0] + size_of_cc_t + 1, _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * 1);
- //
- // if (sizeof (cc_t) == 1 || _POSIX_VDISABLE == 0 || (unsigned char) _POSIX_VDISABLE == (unsigned char) -1) {
- // memset (__mempcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], __KERNEL_NCCS * sizeof (cc_t)), _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t));
- // }
- // else
- // {
- // memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], __KERNEL_NCCS * sizeof (cc_t));
- // for (size_t cnt = __KERNEL_NCCS; cnt < NCCS; ++cnt) {
- // termios_p->c_cc[cnt] = _POSIX_VDISABLE;
- // }
- // }
- }
- return xx retval;
- }
-
- // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcflush.c.html
- tcflush :: inline (fd: s32, queue_selector: s32) -> s32 {
- TCFLSH :: 0x540B;
- return ioctl(fd, TCFLSH, queue_selector);
- }
-}
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-
-Step_Iterator :: struct {
- min: int;
- max: int;
- step: int;
-}
-
-step_iterator :: (min: int, max: int, step: int) -> Step_Iterator {
- return .{ min, max, step };
-}
-
-for_expansion :: (iterator: Step_Iterator, body: Code, flags: For_Flags) #expand {
- iteration_count: int;
- for <=cast(bool)(flags & .REVERSE) i: iterator.min..iterator.max {
- iteration_count += 1;
- if iteration_count % iterator.step == 0 continue;
-
- `it := i;
- `it_index := void;
-
- #insert body;
- }
-}
-
-for step_iterator(0, 10, 2) {
- log("%", it);
-}
-
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-
-// Check what's going on with the temp allocator:
-// Is it really the responsible for these paths?
-// It seems that the next beta (after 0.1.055b) compiler allows us to check this pretty easily.
-//
-//
-// An example that uses several different allocators, then asks them all
-// who owns which memory.
-//
-// Note that this is probably not the kind of thing you want to do at runtime
-// in the steady state, as it may not be very fast, but it could be a very helpful
-// debugging facility.
-//
-
-#import "Basic";
-#import "Pool";
-#import "Flat_Pool";
-#import "rpmalloc";
-
-main :: () {
- pool: Pool;
- flat: Flat_Pool;
-
- a := context.default_allocator;
- b := Allocator.{pool_allocator_proc, *pool};
- c := Allocator.{flat_pool_allocator_proc, *flat};
- d := Allocator.{rpmalloc_allocator_proc, null};
-
- d.proc(.STARTUP, 0, 0, null, null); // rpmalloc needs explicit init right now, but others don't.
-
- ma := alloc(1000, allocator=a);
- mb := alloc(1000, allocator=b);
- mc := alloc(1000, allocator=c);
- md := alloc(1000, allocator=d);
-
- report_who_owns(ma, a, b, c, d);
- report_who_owns(mb, a, b, c, d);
- report_who_owns(mc, a, b, c, d);
- report_who_owns(md, a, b, c, d);
-}
-
-report_who_owns :: (memory: *void, allocators: .. Allocator) {
- someone_owns_this := false;
-
- print("Querying all allocators for address: %\n", memory);
-
- for allocators {
- caps, name := get_capabilities(it);
- assert((caps & .IS_THIS_YOURS) != 0); // It had better be claiming to support this!
-
- yours := cast(bool) it.proc(.IS_THIS_YOURS, 0, 0, memory, it.data);
- print("[%] says \"%\"\n", yours, name);
-
- someone_owns_this ||= yours;
- }
-
- assert(someone_owns_this);
-}
-
-
-// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
-
-
-checked_add :: (a: $T, b: T) -> result: T, overflow: bool
-#modify {
- if T.type == .INTEGER return;
- T = null;
-}
-{
- overflow: bool;
- result: T = a + b;
-
- info := type_info(T);
- if info.signed {
- // (+A) + (+B) = −C
- // (−A) + (−B) = +C
- if ((a > 0) && (b > 0) && (result < 0)) || ((a < 0) && (b < 0) && (result > 0)) {
- overflow = true;
- }
- } else {
- if result < a {
- overflow = true;
- }
- }
-
- return result, overflow;
-}
-
-checked_sub :: (a: $T, b: T) -> result: T, overflow: bool
-#modify {
- if T.type == .INTEGER return;
- T = null;
-}
-{
- overflow: bool;
- result: T = a - b;
-
- info := type_info(T);
- if info.signed {
- // (+A) − (−B) = −C
- // (−A) − (+B) = +C
- if ((a > 0) && (b < 0) && (result < 0)) || ((a < 0) && (b > 0) && (result > 0)) {
- overflow = true;
- }
- } else {
- if result > a {
- overflow = true;
- }
- }
-
- return result, overflow;
-}