nandi/rustnimpublic Fork
⑂ 6e2a88e
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Lower `libc`'s constants through `std/posix`

`inotify-sys` compiles -- 144 lines of content, the seventh of libcosmic's
dependencies to go the whole way.

`libc::O_NONBLOCK` is the C constant of that name, and Nim's `std/posix`
declares the POSIX set under the same names. Both take their values from the
platform's headers, so they agree by construction rather than by a table
someone would have to maintain -- which is the same argument that makes the
`c_type` mapping sound.

The import is gated on use: `std/posix` exports a great many names and a crate
is entitled to its own `Time` or `Stat`. A constant outside the POSIX set
fails at Nim's compile time, by name, rather than silently resolving to
something else.

`tests/cases/082` checks the values against the real `libc` crate through
`//@ extern`, so this is measured against the C headers rather than against a
reading of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-20T15:08:52-07:00 Browse files
6e2a88e parent: 95ac909
modified Cargo.lock +7 -0
@@ -96,6 +96,12 @@ dependencies = [
9696 "slab",
9797 ]
9898
99+[[package]]
100+name = "libc"
101+version = "0.2.189"
102+source = "registry+https://github.com/rust-lang/crates.io-index"
103+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
104+
99105 [[package]]
100106 name = "log"
101107 version = "0.4.34"
@@ -138,6 +144,7 @@ version = "0.1.0"
138144 dependencies = [
139145 "bitflags",
140146 "futures",
147+ "libc",
141148 "log",
142149 "proc-macro2",
143150 "quote",
@@ -96,6 +96,12 @@ dependencies = [
96 "slab",96 "slab",
97 ]97 ]
98 98
99+[[package]]
100+name = "libc"
101+version = "0.2.189"
102+source = "registry+https://github.com/rust-lang/crates.io-index"
103+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
104+
99 [[package]]105 [[package]]
100 name = "log"106 name = "log"
101 version = "0.4.34"107 version = "0.4.34"
@@ -138,6 +144,7 @@ version = "0.1.0"
138 dependencies = [144 dependencies = [
139 "bitflags",145 "bitflags",
140 "futures",146 "futures",
147+ "libc",
141 "log",148 "log",
142 "proc-macro2",149 "proc-macro2",
143 "quote",150 "quote",
modified Cargo.toml +1 -0
@@ -15,3 +15,4 @@ syn = { version = "3.0.5", features = ["full", "extra-traits", "visit", "visit-m
1515 bitflags = "2"
1616 log = "0.4"
1717 futures = "0.3"
18+libc = "0.2"
@@ -15,3 +15,4 @@ syn = { version = "3.0.5", features = ["full", "extra-traits", "visit", "visit-m
15 bitflags = "2"15 bitflags = "2"
16 log = "0.4"16 log = "0.4"
17 futures = "0.3"17 futures = "0.3"
18+libc = "0.2"
modified src/lower.rs +16 -0
@@ -361,6 +361,8 @@ pub struct Lowerer {
361361 /// before the prelude is written.
362362 uses_sync: std::cell::Cell<bool>,
363363 uses_i128: std::cell::Cell<bool>,
364+ /// Whether a `libc::` constant was named, which pulls in `std/posix`.
365+ uses_posix: std::cell::Cell<bool>,
364366 /// Function-local `struct`/`enum` declarations, by name and by the source
365367 /// text of the declaration. Nim has no function-local type namespace, so
366368 /// these land in the module's one namespace; two different types under one
@@ -532,6 +534,7 @@ impl Lowerer {
532534 uses_async: false,
533535 uses_sync: std::cell::Cell::new(false),
534536 uses_i128: std::cell::Cell::new(false),
537+ uses_posix: std::cell::Cell::new(false),
535538 local_items: HashMap::new(),
536539 emitted_local: std::collections::HashSet::new(),
537540 emitted_assoc: std::collections::HashSet::new(),
@@ -933,6 +936,9 @@ impl Lowerer {
933936 if self.uses_i128.get() {
934937 out.push_str(include_str!("prelude_i128.nim"));
935938 }
939+ if self.uses_posix.get() {
940+ out.push_str(include_str!("prelude_posix.nim"));
941+ }
936942 if self.uses_sync.get() {
937943 out.push_str(include_str!("prelude_sync.nim"));
938944 out.push('\n');
@@ -6378,6 +6384,16 @@ impl Lowerer {
63786384 }
63796385 }
63806386
6387+ // `libc::O_NONBLOCK` is the C constant of that name, which
6388+ // `std/posix` declares under the same name and takes from the
6389+ // same header. See `src/prelude_posix.nim`.
6390+ if let Some(q) = p.path.segments.iter().rev().nth(1) {
6391+ if q.ident == "libc" && name.chars().all(|c| c.is_ascii_uppercase() || c == '_' || c.is_ascii_digit()) {
6392+ self.uses_posix.set(true);
6393+ return Ok(Val::new(ident(&name), Some(Nim::Prim("cint".into()))));
6394+ }
6395+ }
6396+
63816397 // `Self::CONST` where `Self` is a type parameter: which
63826398 // constant that is depends on the instantiation, so it is read
63836399 // through the accessor rather than named.
@@ -361,6 +361,8 @@ pub struct Lowerer {
361 /// before the prelude is written.361 /// before the prelude is written.
362 uses_sync: std::cell::Cell<bool>,362 uses_sync: std::cell::Cell<bool>,
363 uses_i128: std::cell::Cell<bool>,363 uses_i128: std::cell::Cell<bool>,
364+ /// Whether a `libc::` constant was named, which pulls in `std/posix`.
365+ uses_posix: std::cell::Cell<bool>,
364 /// Function-local `struct`/`enum` declarations, by name and by the source366 /// Function-local `struct`/`enum` declarations, by name and by the source
365 /// text of the declaration. Nim has no function-local type namespace, so367 /// text of the declaration. Nim has no function-local type namespace, so
366 /// these land in the module's one namespace; two different types under one368 /// these land in the module's one namespace; two different types under one
@@ -532,6 +534,7 @@ impl Lowerer {
532 uses_async: false,534 uses_async: false,
533 uses_sync: std::cell::Cell::new(false),535 uses_sync: std::cell::Cell::new(false),
534 uses_i128: std::cell::Cell::new(false),536 uses_i128: std::cell::Cell::new(false),
537+ uses_posix: std::cell::Cell::new(false),
535 local_items: HashMap::new(),538 local_items: HashMap::new(),
536 emitted_local: std::collections::HashSet::new(),539 emitted_local: std::collections::HashSet::new(),
537 emitted_assoc: std::collections::HashSet::new(),540 emitted_assoc: std::collections::HashSet::new(),
@@ -933,6 +936,9 @@ impl Lowerer {
933 if self.uses_i128.get() {936 if self.uses_i128.get() {
934 out.push_str(include_str!("prelude_i128.nim"));937 out.push_str(include_str!("prelude_i128.nim"));
935 }938 }
939+ if self.uses_posix.get() {
940+ out.push_str(include_str!("prelude_posix.nim"));
941+ }
936 if self.uses_sync.get() {942 if self.uses_sync.get() {
937 out.push_str(include_str!("prelude_sync.nim"));943 out.push_str(include_str!("prelude_sync.nim"));
938 out.push('\n');944 out.push('\n');
@@ -6378,6 +6384,16 @@ impl Lowerer {
6378 }6384 }
6379 }6385 }
6380 6386
6387+ // `libc::O_NONBLOCK` is the C constant of that name, which
6388+ // `std/posix` declares under the same name and takes from the
6389+ // same header. See `src/prelude_posix.nim`.
6390+ if let Some(q) = p.path.segments.iter().rev().nth(1) {
6391+ if q.ident == "libc" && name.chars().all(|c| c.is_ascii_uppercase() || c == '_' || c.is_ascii_digit()) {
6392+ self.uses_posix.set(true);
6393+ return Ok(Val::new(ident(&name), Some(Nim::Prim("cint".into()))));
6394+ }
6395+ }
6396+
6381 // `Self::CONST` where `Self` is a type parameter: which6397 // `Self::CONST` where `Self` is a type parameter: which
6382 // constant that is depends on the instantiation, so it is read6398 // constant that is depends on the instantiation, so it is read
6383 // through the accessor rather than named.6399 // through the accessor rather than named.
added src/prelude_posix.nim +14 -0
new file mode 100644
@@ -0,0 +1,14 @@
1+
2+# ---------------------------------------------------------------------------
3+# `libc`'s constants.
4+#
5+# `libc::O_NONBLOCK` is the C constant of that name, and `std/posix` declares
6+# the POSIX set under the same names with the same values -- both take them
7+# from the platform's headers, so they are equal by construction rather than
8+# by a table someone maintained.
9+#
10+# Imported only when a translated file names one, because `std/posix` exports
11+# a great many names and a crate is entitled to its own `Time` or `Stat`.
12+# A constant outside the POSIX set fails at Nim's compile time, by name.
13+# ---------------------------------------------------------------------------
14+import std/posix
new file mode 100644
@@ -0,0 +1,14 @@
1+
2+# ---------------------------------------------------------------------------
3+# `libc`'s constants.
4+#
5+# `libc::O_NONBLOCK` is the C constant of that name, and `std/posix` declares
6+# the POSIX set under the same names with the same values -- both take them
7+# from the platform's headers, so they are equal by construction rather than
8+# by a table someone maintained.
9+#
10+# Imported only when a translated file names one, because `std/posix` exports
11+# a great many names and a crate is entitled to its own `Time` or `Stat`.
12+# A constant outside the POSIX set fails at Nim's compile time, by name.
13+# ---------------------------------------------------------------------------
14+import std/posix
added tests/cases/082-libc-consts.rs +17 -0
new file mode 100644
@@ -0,0 +1,17 @@
1+//@ extern: libc
2+// `libc::O_NONBLOCK` is the C constant of that name, and Nim's `std/posix`
3+// declares the POSIX set under the same names — both take them from the
4+// platform's headers, so they agree by construction rather than by a table.
5+fn main() {
6+ println!("{}", libc::O_NONBLOCK);
7+ println!("{}", libc::O_CLOEXEC);
8+ println!("{}", libc::EAGAIN);
9+ println!("{}", libc::EINVAL);
10+ println!("{}", libc::SOCK_STREAM);
11+ println!("{}", libc::AF_UNIX);
12+
13+ // Combined the way flags actually get used.
14+ let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
15+ println!("{}", flags);
16+ println!("{}", flags & libc::O_CLOEXEC != 0);
17+}
new file mode 100644
@@ -0,0 +1,17 @@
1+//@ extern: libc
2+// `libc::O_NONBLOCK` is the C constant of that name, and Nim's `std/posix`
3+// declares the POSIX set under the same names — both take them from the
4+// platform's headers, so they agree by construction rather than by a table.
5+fn main() {
6+ println!("{}", libc::O_NONBLOCK);
7+ println!("{}", libc::O_CLOEXEC);
8+ println!("{}", libc::EAGAIN);
9+ println!("{}", libc::EINVAL);
10+ println!("{}", libc::SOCK_STREAM);
11+ println!("{}", libc::AF_UNIX);
12+
13+ // Combined the way flags actually get used.
14+ let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
15+ println!("{}", flags);
16+ println!("{}", flags & libc::O_CLOEXEC != 0);
17+}