diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 15:11:00 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 15:11:00 +0000 |
| commit | 55247a3f12a9eee7ba3fd7ca6d8fcea7a82c20f3 (patch) | |
| tree | a2a71e2eb8ca0b2c483518c1902d89d18709c9ab /src/zen | |
| parent | 2e7abed7cfe84a2c0df371cde35f8f68cfdca16c (diff) | |
Added src/ folder. Now I will add the rest.
Diffstat (limited to 'src/zen')
| -rw-r--r-- | src/zen/zen_facts.c | 415 | ||||
| -rw-r--r-- | src/zen/zen_facts.h | 32 |
2 files changed, 447 insertions, 0 deletions
diff --git a/src/zen/zen_facts.c b/src/zen/zen_facts.c new file mode 100644 index 0000000..441a180 --- /dev/null +++ b/src/zen/zen_facts.c @@ -0,0 +1,415 @@ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include "zen_facts.h" + +// We keep it low by default. +#define ZEN_PROBABILITY 10 + +typedef struct +{ + ZenTrigger trigger; + const char *message; + const char *url; +} ZenFact; + +static const ZenFact facts[] = { + {TRIGGER_GOTO, + "Edsger W. Dijkstra considered 'Go To Statement Harmful' in 1968, advocating for structured " + "programming.", + "https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf"}, + {TRIGGER_GOTO, + "Goto can be useful for error cleanup patterns in C (and Zen C), mimicking 'defer' or " + "'finally' blocks.", + NULL}, + + {TRIGGER_POINTER_ARITH, + "In C, `arr[i]` is just `*(arr + i)`. Fun fact: `i[arr]` is also valid syntax!", + "https://c-faq.com/aryptr/aryptr2.html"}, + {TRIGGER_POINTER_ARITH, + "Pointer arithmetic scales by the size of the type. `ptr + 1` increases the address by " + "`sizeof(*ptr)` bytes.", + NULL}, + + {TRIGGER_BITWISE, "Use `(x & (x - 1)) == 0` to check if an integer is a power of two.", + "https://graphics.stanford.edu/~seander/bithacks.html"}, + {TRIGGER_BITWISE, + "XOR swap algorithm: `x ^= y; y ^= x; x ^= y;` swaps variables without a temporary (but " + "optimized code is usually faster).", + NULL}, + + {TRIGGER_RECURSION, "To understand recursion, you must first understand recursion.", NULL}, + {TRIGGER_RECURSION, + "Tail Call Optimization (TCO) allows some recursive calls to consume no additional stack " + "space.", + "https://en.wikipedia.org/wiki/Tail_call"}, + + {TRIGGER_TERNARY, + "The ternary operator `?:` is the only operator in C that takes three operands.", NULL}, + + {TRIGGER_ASM, + "With great power comes great responsibility. Inline assembly is compiler-specific and " + "fragile.", + NULL}, + + {TRIGGER_WHILE_TRUE, + "The Halting Problem proves it is impossible to determine if an arbitrary program will " + "eventually stop.", + "https://en.wikipedia.org/wiki/Halting_problem"}, + + {TRIGGER_MACRO, + "Macros are handled by the preprocessor, doing simple text replacement before compilation " + "begins.", + NULL}, + + {TRIGGER_VOID_PTR, + "A `void*` is a generic pointer type. You cannot dereference it directly without casting.", + NULL}, + + {TRIGGER_POINTER_ARITH, + "Subtracting two pointers returns a `ptrdiff_t`, a signed integer type capable of holding the " + "difference.", + NULL}, + + {TRIGGER_MAIN, + "In C, `main` implicitly returns 0 if no return statement is found (C99+). Zen C follows " + "suit.", + NULL}, + + {TRIGGER_FORMAT_STRING, + "printf format strings are a mini-language interpreted at runtime. Be careful with user " + "input!", + NULL}, + + {TRIGGER_BITWISE, + "The `!!` idiom (double negation) is a standard way to normalize any non-zero value to " + "exactly 1.", + NULL}, + + {TRIGGER_GLOBAL, + "Duff's Device interleaves a switch statement with a do-while loop to unroll copy loops.", + "https://en.wikipedia.org/wiki/Duff%27s_device"}, + {TRIGGER_GLOBAL, + "In C, `sizeof` is an operator, not a function. Parentheses are only required for type names.", + NULL}, + {TRIGGER_GLOBAL, + "Digraphs and Trigraphs were added for keyboards missing symbols. `\\?\\?=` is `#`, and `<:` " + "is `[`.", + "https://en.wikipedia.org/wiki/Digraphs_and_trigraphs"}, + {TRIGGER_GLOBAL, + "Function designators convert to pointers automatically. `foo`, `&foo`, and `*foo` all " + "resolve to the same address.", + NULL}, + {TRIGGER_GLOBAL, + "The comma operator evaluates operands left-to-right and returns the last. `x = (1, 2, 3)` " + "sets x to 3.", + NULL}, + {TRIGGER_GLOBAL, + "Multi-character constants like 'ABCD' are valid C. Their integer value is " + "implementation-defined.", + NULL}, + {TRIGGER_GLOBAL, + "Bit-fields allow packing struct members into specific bit widths. `int x : 3;` uses only 3 " + "bits.", + NULL}, + {TRIGGER_GLOBAL, + "Array indexing is commutative: `5[arr]` is semantically identical to `arr[5]`.", NULL}, + {TRIGGER_GLOBAL, + "The `restrict` keyword promises the compiler that a pointer is the only access to that " + "memory.", + NULL}, + {TRIGGER_GLOBAL, + "A struct's size can be larger than the sum of its members due to alignment padding.", NULL}, + {TRIGGER_GLOBAL, + "In C, `void*` arithmetic is a GCC extension (treating size as 1). Standard C forbids it.", + NULL}, + {TRIGGER_GLOBAL, + "The C standard guarantees that `NULL` equals `(void*)0`, but the bit pattern may not be all " + "zeros.", + NULL}, + {TRIGGER_GLOBAL, + "`sizeof('a')` is 4 in C (int) but 1 in C++ (char). A subtle difference between the " + "languages.", + NULL}, + {TRIGGER_GLOBAL, + "Static local variables are initialized only once, even if the function is called multiple " + "times.", + NULL}, + {TRIGGER_GLOBAL, + "The `volatile` keyword prevents compiler optimizations on a variable, useful for hardware " + "registers.", + NULL}, + {TRIGGER_GLOBAL, + "In C99+, Variable Length Arrays (VLAs) can have runtime-determined sizes. Use with caution!", + NULL}, + {TRIGGER_GLOBAL, "The `_Alignof` operator (C11) returns the alignment requirement of a type.", + NULL}, + {TRIGGER_GLOBAL, + "Compound literals like `(int[]){1, 2, 3}` create anonymous arrays with automatic storage.", + NULL}, + {TRIGGER_GLOBAL, + "Designated initializers: `.field = val` lets you initialize struct fields out of order.", + NULL}, + {TRIGGER_GLOBAL, + "The `#` stringification operator in macros turns arguments into string literals.", NULL}, + {TRIGGER_GLOBAL, "The `##` token-pasting operator concatenates tokens in macro expansions.", + NULL}, + {TRIGGER_GLOBAL, + "Flexible array members: `int data[];` at struct end allows variable-size structs.", NULL}, + {TRIGGER_GLOBAL, + "Anonymous structs/unions (C11) allow direct member access without field names.", NULL}, + {TRIGGER_GLOBAL, + "`_Generic` (C11) provides compile-time type dispatch, like a simpler form of overloading.", + NULL}, + {TRIGGER_GLOBAL, + "The `register` keyword is a hint to the compiler, but modern compilers ignore it.", NULL}, + {TRIGGER_GLOBAL, "Integer promotion: `char` and `short` are promoted to `int` in expressions.", + NULL}, + {TRIGGER_GLOBAL, + "Signed integer overflow is undefined behavior in C. Use unsigned for wrap-around arithmetic.", + NULL}, + {TRIGGER_GLOBAL, + "The order of evaluation for function arguments is unspecified in C. Never rely on it!", NULL}, + {TRIGGER_GLOBAL, "In C, you can take the address of a label with `&&label` (GCC extension).", + NULL}, + {TRIGGER_GLOBAL, + "The `inline` keyword is only a suggestion. Compilers decide whether to actually inline.", + NULL}, + {TRIGGER_GLOBAL, + "`setjmp`/`longjmp` provide non-local jumps, but are dangerous and rarely needed.", NULL}, + {TRIGGER_GLOBAL, + "The `#pragma once` directive is non-standard but widely supported for include guards.", NULL}, + {TRIGGER_GLOBAL, + "A `char` can be signed or unsigned depending on the platform. Use `signed char` or `unsigned " + "char` to be explicit.", + NULL}, + {TRIGGER_GLOBAL, + "The `const` keyword doesn't make data immutable - you can cast it away (but shouldn't).", + NULL}, + {TRIGGER_GLOBAL, + "C has no native boolean type before C99. `_Bool` was added in C99, `bool` via stdbool.h.", + NULL}, + {TRIGGER_GLOBAL, + "Empty parameter lists in C mean 'unspecified arguments', not 'no arguments'. Use `(void)` " + "for none.", + NULL}, + {TRIGGER_GLOBAL, + "The `extern` keyword declares a variable without defining it, linking to another translation " + "unit.", + NULL}, + {TRIGGER_GLOBAL, + "K&R style function definitions predate ANSI C and put parameter types after the parentheses.", + NULL}, + {TRIGGER_GLOBAL, + "The IOCCC (Obfuscated C Code Contest) showcases creative abuse of C syntax since 1984.", + "https://www.ioccc.org"}, + {TRIGGER_GLOBAL, + "Dennis Ritchie developed C at Bell Labs between 1969-1973. It replaced B, which was " + "typeless.", + NULL}, + {TRIGGER_GLOBAL, "The name 'C' simply comes from being the successor to the B language.", NULL}, + {TRIGGER_GLOBAL, + "Plan 9 C allows `structure.member` notation even if `member` is inside an anonymous inner " + "struct. C11 finally adopted this!", + "https://9p.io/sys/doc/comp.html"}, + {TRIGGER_GLOBAL, + "In Plan 9 C, arrays of zero length `int data[0]` were valid long before C99 flexible array " + "members.", + NULL}, + {TRIGGER_GLOBAL, + "Plan 9 C headers are 'idempotent' — they contain their own include guards, so you never see " + "`#ifndef HEADER_H` boilerplate.", + NULL}, + {TRIGGER_GLOBAL, + "In Plan 9, the `nil` pointer is distinct from 0. Accessing `nil` causes a hardware trap, not " + "just undefined behavior.", + NULL}, + {TRIGGER_GLOBAL, + "Ken Thompson, creator of B and C, also designed UTF-8 encoding on a placemat in a New Jersey " + "diner.", + "https://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt"}, + {TRIGGER_GLOBAL, + "C11 introduced `_Noreturn` to tell the compiler a function (like `exit`) will never return " + "control to the caller.", + NULL}, + {TRIGGER_GLOBAL, + "A 'Sequence Point' is a juncture where all side effects of previous evaluations must be " + "complete. Violation = UB.", + "https://en.wikipedia.org/wiki/Sequence_point"}, + {TRIGGER_GLOBAL, + "VLAs were mandatory in C99, but made optional in C11 because they are hard to implement " + "safely.", + NULL}, + {TRIGGER_GLOBAL, + "Pre-ANSI C (K&R) didn't have `void`. Functions returning nothing actually returned an " + "undefined `int`.", + NULL}, + {TRIGGER_GLOBAL, + "Adjacent string literals are concatenated automatically. `\"Hello \" \"World\"` becomes " + "`\"Hello World\"`.", + NULL}, + {TRIGGER_GLOBAL, + "The `auto` keyword exists in C! It declares automatic storage duration, but is almost never " + "used since it's the default.", + NULL}, + {TRIGGER_GLOBAL, + "Bitwise operators have lower precedence than comparisons! `val & MASK == 0` is `val & (MASK " + "== 0)`. Always parenthesize!", + NULL}, + {TRIGGER_GLOBAL, + "The 'as-if' rule allows compilers to transform code however they want, as long as observable " + "behavior remains the same.", + "https://en.cppreference.com/w/c/language/as_if"}, + {TRIGGER_GLOBAL, + "Tail Recursion Elimination (TRE) isn't guaranteed by the C standard, but most compilers do " + "it at -O2.", + NULL}, + {TRIGGER_GLOBAL, + "GCC's `__builtin_expect` allows you to tell the branch predictor which path is more likely " + "(the `likely()` macro).", + NULL}, + {TRIGGER_GLOBAL, "The actual inspiration for this project was this video.", + "https://youtu.be/vXYVfk7agqU?si=fjbB9iwdmL8Qhjol"}, // Have fun. +}; + +static int fact_count = sizeof(facts) / sizeof(ZenFact); +static int has_triggered = 0; + +void zen_init(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + srand(ts.tv_nsec ^ getpid()); +} + +// Global helper to print. +void zzen_at(Token t, const char *msg, const char *url) +{ + fprintf(stderr, "\033[1;35mzen: \033[0m\033[1m%s\033[0m\n", msg); + + extern char *g_current_filename; + if (t.line > 0) + { + fprintf(stderr, COLOR_BLUE " --> " COLOR_RESET "%s:%d:%d\n", + g_current_filename ? g_current_filename : "unknown", t.line, t.col); + } + + if (t.start) + { + const char *line_start = t.start - (t.col - 1); + const char *line_end = t.start; + while (*line_end && '\n' != *line_end) + { + line_end++; + } + int line_len = line_end - line_start; + + fprintf(stderr, COLOR_BLUE " |\n" COLOR_RESET); + fprintf(stderr, COLOR_BLUE "%-3d| " COLOR_RESET "%.*s\n", t.line, line_len, line_start); + fprintf(stderr, COLOR_BLUE " | " COLOR_RESET); + for (int i = 0; i < t.col - 1; i++) + { + fprintf(stderr, " "); + } + fprintf(stderr, "\033[1;35m^ zen tip\033[0m\n"); + } + + if (url) + { + fprintf(stderr, COLOR_CYAN " = read more: %s" COLOR_RESET "\n", url); + } +} + +int zen_trigger_at(ZenTrigger t, Token location) +{ + if (g_config.quiet) + { + return 0; + } + + if (has_triggered) + { + return 0; + } + + if ((rand() % 100) >= ZEN_PROBABILITY) + { + return 0; + } + + int matches[10]; + int match_count = 0; + + for (int i = 0; i < fact_count; i++) + { + if (facts[i].trigger == t) + { + matches[match_count++] = i; + if (match_count >= 10) + { + break; + } + } + } + + if (0 == match_count) + { + return 0; + } + + int pick = matches[rand() % match_count]; + const ZenFact *f = &facts[pick]; + + zzen_at(location, f->message, f->url); + has_triggered = 1; + return 1; +} + +void zen_trigger_global(void) +{ + if (g_config.quiet) + { + return; + } + if (!isatty(STDERR_FILENO)) + { + return; + } + if (has_triggered) + { + return; + } + + if ((rand() % 100) >= ZEN_PROBABILITY) + { + return; + } + + int matches[10]; + int match_count = 0; + + for (int i = 0; i < fact_count; i++) + { + if (TRIGGER_GLOBAL == facts[i].trigger) + { + matches[match_count++] = i; + if (match_count >= 10) + { + break; + } + } + } + + if (0 == match_count) + { + return; + } + + int pick = matches[rand() % match_count]; + const ZenFact *f = &facts[pick]; + + Token empty = {0}; + zzen_at(empty, f->message, f->url); + has_triggered = 1; +} diff --git a/src/zen/zen_facts.h b/src/zen/zen_facts.h new file mode 100644 index 0000000..ce5b952 --- /dev/null +++ b/src/zen/zen_facts.h @@ -0,0 +1,32 @@ + +#ifndef ZEN_FACTS_H +#define ZEN_FACTS_H + +#include "../zprep.h" + +typedef enum +{ + TRIGGER_GOTO, + TRIGGER_POINTER_ARITH, + TRIGGER_BITWISE, + TRIGGER_RECURSION, + TRIGGER_TERNARY, + TRIGGER_ASM, + TRIGGER_WHILE_TRUE, + TRIGGER_MACRO, + TRIGGER_VOID_PTR, + TRIGGER_MAIN, + TRIGGER_FORMAT_STRING, + TRIGGER_STRUCT_PADDING, + TRIGGER_GLOBAL +} ZenTrigger; + +void zen_init(void); + +int zen_trigger_at(ZenTrigger t, Token location); + +void zen_trigger_global(void); + +const char *zen_get_fact(ZenTrigger t); + +#endif |
