{"id":29091092,"url":"https://github.com/fuhsnn/c-extensions","last_synced_at":"2025-06-28T06:04:49.141Z","repository":{"id":300889389,"uuid":"1007229599","full_name":"fuhsnn/c-extensions","owner":"fuhsnn","description":"Extensions to C language implemented as patches to slimcc","archived":false,"fork":false,"pushed_at":"2025-06-24T04:30:37.000Z","size":731,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-24T05:32:15.310Z","etag":null,"topics":["c","c-compiler","compiler"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fuhsnn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-23T16:57:34.000Z","updated_at":"2025-06-24T04:30:40.000Z","dependencies_parsed_at":"2025-06-24T05:32:18.375Z","dependency_job_id":"6bce5904-9907-4b76-87c4-d28181520ea7","html_url":"https://github.com/fuhsnn/c-extensions","commit_stats":null,"previous_names":["fuhsnn/c-extensions"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fuhsnn/c-extensions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuhsnn%2Fc-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuhsnn%2Fc-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuhsnn%2Fc-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuhsnn%2Fc-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fuhsnn","download_url":"https://codeload.github.com/fuhsnn/c-extensions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuhsnn%2Fc-extensions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262382725,"owners_count":23302295,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","c-compiler","compiler"],"created_at":"2025-06-28T06:04:47.448Z","updated_at":"2025-06-28T06:04:49.129Z","avatar_url":"https://github.com/fuhsnn.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"This is a collection of extensions to C programming language implemented as patches to the [slimcc](https://github.com/fuhsnn/slimcc) compiler, done mostly for fun, may not be well thought out. They're kept in [separate branches](https://github.com/fuhsnn/c-extensions/branches) for better view-ability and to keep upstream codebase flexible. For building the compiler please refer to [upstream readme](https://github.com/fuhsnn/slimcc?tab=readme-ov-file#building-and-using).\n\n - [`for LoopName (...)`](#alt-named-loops-syntax)\n - [`[[gate(allowlist)]]`](#attr-gate)\n - [`_Match_type()`](#match-type)\n - [`_Match_int()`](#match-int)\n\n\u003ca name=\"alt-named-loops-syntax\"\u003e\u003c/a\u003e\n## [Alternative C2Y named loops syntax](https://github.com/fuhsnn/c-extensions/tree/alt-named-loops-syntax)\n\nAn implementation of the [n3377 proposal to WG14](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf) because I'm sympathetic to it.\n\nIt's done on top of the label-based syntax, so those still work. `do while` loops are implemented differently because slimcc's current structure is too single-pass-y to support it elegantly, the name is positioned after `do` and only work for curly braced blocks.\n\nRunnable example:\n```C\n#include \u003cstdio.h\u003e\n\nint main(void) {\n  int i = 0;\n  do DW1 {\n    For_lab2:\n    for For_lab1 (int j = 0; j \u003c 10; j++) {\n        switch S1 (j) {\n        case 3:\n            break;\n        case 2:\n            continue For_lab1;\n        case 5:\n            break S1;\n        default:\n            continue;\n        }\n        if ((i % j) == 0) {\n            printf(\"%d\\n\",i);\n            break For_lab2;\n        }\n    }\n    while W1 (i++ \u003e 25)\n        break DW1;\n  } while (1);\n}\n```\n\n\u003ca name=\"attr-gate\"\u003e\u003c/a\u003e\n## [Block attribute `[[gate(allowlist)]]`](https://github.com/fuhsnn/c-extensions/tree/attr-gate)\n\nThe attribute act as a guarded gate that only allow identifiers listed in `allowlist` to be referenced from inside the following block. It can be applied to normal blocks, secondary-blocks, statement-expressions as well as function bodies.\n```C\nint foo, bar, baz;\n[[slimcc::gate(foo, baz)]] {\n  foo += baz;\n  bar += 2; // error, bar isn't in allowlist, it's an undefined variable here.\n}\n```\nIts intended use is to make complex function-like macros less leaky, like:\n```C\n// #def and #enddef from N3531 proposal\n#def Psuedo_template_fn(Tr, T1, T2, arg1, arg2)\n  ({\n    typeof(T1) v1 = (arg1);\n    typeof(T2) v2 = (arg2);\n\n    (typeof(Tr)) [[slimcc::gate(v1, v2, exit)]] ({\n      /* only v1, v2 and exit() are usable in this statement-expression,\n        just like regular functions, stricter in fact */\n    });\n  })\n#enddef\n```\nCompilable example, also try it with gcc/clang to see the difference:\n```C\n#include \u003cstdlib.h\u003e\n\n#ifdef __has_c_attribute\n#if __has_c_attribute(slimcc::gate)\n#define GATE(allow_list...) [[slimcc::gate(allow_list)]]\n#endif\n#endif\n\n#ifndef GATE\n#define GATE(...)\n#endif\n\nstruct Linked {\n  struct Linked *next;\n};\n\n#define Macro_w_typo(_x)          \\\n  do GATE(_x, free) {             \\\n    __auto_type nxt = (_x)-\u003enext; \\\n    free(x /*typo*/);             \\\n    _x = nxt;                     \\\n  } while(0)\n\nvoid fn(struct Linked *x, struct Linked *y) {\n  Macro_w_typo(y); // error: \"x\" undefined instead of silently using same named var\n}\n\nint psuedo_pure_func(int i) GATE(i) { // applicable to function body\n\n  fn(NULL, NULL); // error: fn unusable here since it's not in allow list\n\n  int g = GATE(i)({ i - 1; }); // also applicable to statement-expression\n  return g - 1;\n}\n\nint main(void) {\n  return psuedo_pure_func(2);\n}\n```\n\n\u003ca name=\"match-type\"\u003e\u003c/a\u003e\n## [`_Match_type(type/expr, type:(expr), ...)`](https://github.com/fuhsnn/c-extensions/tree/match-type-int)\n\nAs a response to Simon Tatham's [Workarounds for C11 _Generic](https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/), this is a version of `_Generic` that chooses from parentheses-balanced tokens without semantic checking until the selection is made. The result still needs to be a complete expression, more complex stuff can be done with statement-expression.\n\nRunnable example:\n```C\n#include \u003cstdio.h\u003e\n#include \u003cstring.h\u003e\n\nstruct MyStringBuffer {\n  char *data;\n  size_t length;\n};\n\n// #def and #enddef from N3531 proposal\n#def string_length(x)\n  _Match_type(x,\n    char *                  : (strlen(x)),\n    struct MyStringBuffer * : ((x)-\u003elength)\n  )\n#enddef\n\nint main() {\n  struct MyStringBuffer buf = {\"sliced\", 3};\n  printf(\"size %d\\n\", (int)string_length(\u0026buf));\n\n  printf(\"size %d\\n\", (int)string_length(\"foobar\"));\n}\n```\n\n\u003ca name=\"match-int\"\u003e\u003c/a\u003e\n## [`_Match_int(const_expr, const_expr:(expr), ...)`](https://github.com/fuhsnn/c-extensions/tree/match-type-int)\n\nLike `_Match_type` but chooses from integer constant expressions instead, in other words, compile-time expression selection with pattern-matching syntax. It also tries to be less sloppy by requiring case numbers to be the same integer type without implicit conversion.\n\nRunnable example:\n```C\n#include \u003cstdio.h\u003e\n\nint main() {\n  puts(_Match_int(__STDC_VERSION__,\n    202311L : ( \"C23\" ),\n    201710L : ( \"C17\" ),\n    201112L : ( \"C11\" ),\n    199901L : ( \"C99\" ),\n    0L : ( paren-balanced invalid syntax )\n  ));\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuhsnn%2Fc-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuhsnn%2Fc-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuhsnn%2Fc-extensions/lists"}