1#![cfg_attr(not(test), no_std)]
2#![feature(c_variadic)]
3#![feature(linkage)]
4#![feature(f128)]
5#![allow(dead_code, non_camel_case_types)]
6
7use core::ffi::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void, VaList};
8use core::ptr::null_mut;
9use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering};
10
11include!("encoding_tables.rs");
12include!("math_helpers.rs");
13include!("math_bitmanip.rs");
14include!("math_sqrtfmod.rs");
15include!("math_trig.rs");
16include!("math_exp.rs");
17include!("math_log.rs");
18include!("math_pow.rs");
19include!("math_hypot.rs");
20include!("math_hyperbolic.rs");
21include!("math_invtrig.rs");
22include!("math_lrint.rs");
23
24const EILSEQ: c_int = 84;
29const EINVAL: c_int = 22;
30const EFAULT: c_int = 14;
31const E2BIG: c_int = 7;
32
33const LC_CTYPE: c_int = 0;
34const LC_NUMERIC: c_int = 1;
35const LC_TIME: c_int = 2;
36const LC_COLLATE: c_int = 3;
37const LC_MONETARY: c_int = 4;
38const LC_MESSAGES: c_int = 5;
39const LC_ALL: c_int = 6;
40const ENOMEM: c_int = 12;
41const EINTR: c_int = 4;
42const EPERM: c_int = 1;
43const EAGAIN: c_int = 11;
44const EBUSY: c_int = 16;
45const EDEADLK: c_int = 35;
46const ETIMEDOUT: c_int = 110;
47const ECANCELED: c_int = 125;
48const EOVERFLOW: c_int = 75;
49const EOWNERDEAD: c_int = 130;
50const ENOTRECOVERABLE: c_int = 131;
51
52static mut ERRNO: c_int = 0;
53
54#[no_mangle]
55pub unsafe extern "C" fn __errno_location() -> *mut c_int {
56 core::ptr::addr_of_mut!(ERRNO)
57}
58
59#[cfg(not(test))]
60#[panic_handler]
61fn panic(_: &core::panic::PanicInfo) -> ! {
62 loop {}
63}
64
65#[cfg(not(test))]
67#[no_mangle]
68pub extern "C" fn rust_eh_personality() {}
69
70const PROT_READ: i32 = 1;
75const PROT_WRITE: i32 = 2;
76const MAP_SHARED: i32 = 0x01;
77const MAP_PRIVATE: i32 = 0x02;
78const MAP_ANONYMOUS: i32 = 0x20;
79
80trait Syscalls {
85 unsafe fn syscall0(n: i64) -> i64;
86 unsafe fn syscall1(n: i64, a1: i64) -> i64;
87 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
88 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
89 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
90 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
91 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
92 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
93}
94
95struct X86_64;
96struct Aarch64;
97struct Riscv64;
98
99#[cfg(target_arch = "x86_64")]
100impl Syscalls for X86_64 {
101 #[inline(always)]
102 unsafe fn syscall0(n: i64) -> i64 {
103 let result: i64;
104 core::arch::asm!(
105 "syscall",
106 inlateout("rax") n => result,
107 lateout("rcx") _,
108 lateout("r11") _,
109 );
110 result
111 }
112 #[inline(always)]
113 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
114 let result: i64;
115 core::arch::asm!(
116 "syscall",
117 inlateout("rax") n => result,
118 in("rdi") a1,
119 lateout("rcx") _,
120 lateout("r11") _,
121 );
122 result
123 }
124 #[inline(always)]
125 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
126 let result: i64;
127 core::arch::asm!(
128 "syscall",
129 inlateout("rax") n => result,
130 in("rdi") a1,
131 in("rsi") a2,
132 lateout("rcx") _,
133 lateout("r11") _,
134 );
135 result
136 }
137 #[inline(always)]
138 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
139 let result: i64;
140 core::arch::asm!(
141 "syscall",
142 inlateout("rax") n => result,
143 in("rdi") a1,
144 in("rsi") a2,
145 in("rdx") a3,
146 lateout("rcx") _,
147 lateout("r11") _,
148 );
149 result
150 }
151 #[inline(always)]
152 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
153 let result: i64;
154 core::arch::asm!(
155 "syscall",
156 inlateout("rax") n => result,
157 in("rdi") a1,
158 in("rsi") a2,
159 in("rdx") a3,
160 in("r10") a4,
161 lateout("rcx") _,
162 lateout("r11") _,
163 );
164 result
165 }
166 #[inline(always)]
167 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
168 let result: i64;
169 core::arch::asm!(
170 "syscall",
171 inlateout("rax") n => result,
172 in("rdi") a1,
173 in("rsi") a2,
174 in("rdx") a3,
175 in("r10") a4,
176 in("r8") a5,
177 lateout("rcx") _,
178 lateout("r11") _,
179 );
180 result
181 }
182 #[inline(always)]
183 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
184 let result: i64;
185 core::arch::asm!(
186 "syscall",
187 inlateout("rax") n => result,
188 in("rdi") a1,
189 in("rsi") a2,
190 in("rdx") a3,
191 in("r10") a4,
192 in("r8") a5,
193 in("r9") a6,
194 lateout("rcx") _,
195 lateout("r11") _,
196 );
197 result
198 }
199 #[inline(always)]
200 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
201 core::arch::asm!(
202 "syscall",
203 in("rax") n,
204 in("rdi") a1,
205 options(noreturn)
206 );
207 }
208}
209
210#[cfg(target_arch = "aarch64")]
211impl Syscalls for Aarch64 {
212 #[inline(always)]
213 unsafe fn syscall0(n: i64) -> i64 {
214 let result: i64;
215 core::arch::asm!(
216 "svc #0",
217 inlateout("x8") n => _,
218 lateout("x0") result,
219 options(nostack),
220 );
221 result
222 }
223 #[inline(always)]
224 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
225 let result: i64;
226 core::arch::asm!(
227 "svc #0",
228 inlateout("x8") n => _,
229 inlateout("x0") a1 => result,
230 options(nostack),
231 );
232 result
233 }
234 #[inline(always)]
235 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
236 let result: i64;
237 core::arch::asm!(
238 "svc #0",
239 inlateout("x8") n => _,
240 inlateout("x0") a1 => result,
241 inlateout("x1") a2 => _,
242 options(nostack),
243 );
244 result
245 }
246 #[inline(always)]
247 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
248 let result: i64;
249 core::arch::asm!(
250 "svc #0",
251 inlateout("x8") n => _,
252 inlateout("x0") a1 => result,
253 inlateout("x1") a2 => _,
254 inlateout("x2") a3 => _,
255 options(nostack),
256 );
257 result
258 }
259 #[inline(always)]
260 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
261 let result: i64;
262 core::arch::asm!(
263 "svc #0",
264 inlateout("x8") n => _,
265 inlateout("x0") a1 => result,
266 inlateout("x1") a2 => _,
267 inlateout("x2") a3 => _,
268 inlateout("x3") a4 => _,
269 options(nostack),
270 );
271 result
272 }
273 #[inline(always)]
274 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
275 let result: i64;
276 core::arch::asm!(
277 "svc #0",
278 inlateout("x8") n => _,
279 inlateout("x0") a1 => result,
280 inlateout("x1") a2 => _,
281 inlateout("x2") a3 => _,
282 inlateout("x3") a4 => _,
283 inlateout("x4") a5 => _,
284 options(nostack),
285 );
286 result
287 }
288 #[inline(always)]
289 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
290 let result: i64;
291 core::arch::asm!(
292 "svc #0",
293 inlateout("x8") n => _,
294 inlateout("x0") a1 => result,
295 inlateout("x1") a2 => _,
296 inlateout("x2") a3 => _,
297 inlateout("x3") a4 => _,
298 inlateout("x4") a5 => _,
299 inlateout("x5") a6 => _,
300 options(nostack),
301 );
302 result
303 }
304 #[inline(always)]
305 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
306 core::arch::asm!(
307 "svc #0",
308 in("x8") n,
309 in("x0") a1,
310 options(noreturn, nostack),
311 );
312 }
313}
314
315#[cfg(target_arch = "riscv64")]
316impl Syscalls for Riscv64 {
317 #[inline(always)]
318 unsafe fn syscall0(n: i64) -> i64 {
319 let result: i64;
320 core::arch::asm!(
321 "ecall",
322 inlateout("a7") n => _,
323 lateout("a0") result,
324 options(nostack),
325 );
326 result
327 }
328 #[inline(always)]
329 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
330 let result: i64;
331 core::arch::asm!(
332 "ecall",
333 inlateout("a7") n => _,
334 inlateout("a0") a1 => result,
335 options(nostack),
336 );
337 result
338 }
339 #[inline(always)]
340 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
341 let result: i64;
342 core::arch::asm!(
343 "ecall",
344 inlateout("a7") n => _,
345 inlateout("a0") a1 => result,
346 inlateout("a1") a2 => _,
347 options(nostack),
348 );
349 result
350 }
351 #[inline(always)]
352 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
353 let result: i64;
354 core::arch::asm!(
355 "ecall",
356 inlateout("a7") n => _,
357 inlateout("a0") a1 => result,
358 inlateout("a1") a2 => _,
359 inlateout("a2") a3 => _,
360 options(nostack),
361 );
362 result
363 }
364 #[inline(always)]
365 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
366 let result: i64;
367 core::arch::asm!(
368 "ecall",
369 inlateout("a7") n => _,
370 inlateout("a0") a1 => result,
371 inlateout("a1") a2 => _,
372 inlateout("a2") a3 => _,
373 inlateout("a3") a4 => _,
374 options(nostack),
375 );
376 result
377 }
378 #[inline(always)]
379 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
380 let result: i64;
381 core::arch::asm!(
382 "ecall",
383 inlateout("a7") n => _,
384 inlateout("a0") a1 => result,
385 inlateout("a1") a2 => _,
386 inlateout("a2") a3 => _,
387 inlateout("a3") a4 => _,
388 inlateout("a4") a5 => _,
389 options(nostack),
390 );
391 result
392 }
393 #[inline(always)]
394 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
395 let result: i64;
396 core::arch::asm!(
397 "ecall",
398 inlateout("a7") n => _,
399 inlateout("a0") a1 => result,
400 inlateout("a1") a2 => _,
401 inlateout("a2") a3 => _,
402 inlateout("a3") a4 => _,
403 inlateout("a4") a5 => _,
404 inlateout("a5") a6 => _,
405 options(nostack),
406 );
407 result
408 }
409 #[inline(always)]
410 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
411 core::arch::asm!(
412 "ecall",
413 in("a7") n,
414 in("a0") a1,
415 options(noreturn, nostack),
416 );
417 }
418}
419
420#[cfg(target_arch = "x86_64")]
421type Arch = X86_64;
422#[cfg(target_arch = "aarch64")]
423type Arch = Aarch64;
424#[cfg(target_arch = "riscv64")]
425type Arch = Riscv64;
426
427
428
429#[cfg(target_arch = "x86_64")]
431mod sysnr {
432 pub const SYS_READ: i64 = 0;
433 pub const SYS_WRITE: i64 = 1;
434 pub const SYS_OPEN: i64 = 2;
435 pub const SYS_CLOSE: i64 = 3;
436 pub const SYS_STAT: i64 = 4;
437 pub const SYS_FSTAT: i64 = 5;
438 pub const SYS_LSEEK: i64 = 8;
439 pub const SYS_MMAP: i64 = 9;
440 pub const SYS_MUNMAP: i64 = 11;
441 pub const SYS_RT_SIGACTION: i64 = 13;
442 pub const SYS_RT_SIGPROCMASK: i64 = 14;
443 pub const SYS_IOCTL: i64 = 16;
444 pub const SYS_ACCESS: i64 = 21;
445 pub const SYS_SHMGET: i64 = 29;
446 pub const SYS_SHMAT: i64 = 30;
447 pub const SYS_SHMCTL: i64 = 31;
448 pub const SYS_DUP: i64 = 32;
449 pub const SYS_NANOSLEEP: i64 = 35;
450 pub const SYS_SETITIMER: i64 = 38;
451 pub const SYS_ALARM: i64 = 37;
452 pub const SYS_SOCKET: i64 = 41;
453 pub const SYS_CONNECT: i64 = 42;
454 pub const SYS_ACCEPT: i64 = 43;
455 pub const SYS_SENDTO: i64 = 44;
456 pub const SYS_RECVFROM: i64 = 45;
457 pub const SYS_SHUTDOWN: i64 = 48;
458 pub const SYS_BIND: i64 = 49;
459 pub const SYS_LISTEN: i64 = 50;
460 pub const SYS_GETSOCKNAME: i64 = 51;
461 pub const SYS_SOCKETPAIR: i64 = 53;
462 pub const SYS_SETSOCKOPT: i64 = 54;
463 pub const SYS_EXECVE: i64 = 59;
464 pub const SYS_WAIT4: i64 = 61;
465 pub const SYS_KILL: i64 = 62;
466 pub const SYS_UNAME: i64 = 63;
467 pub const SYS_SEMGET: i64 = 64;
468 pub const SYS_SEMOP: i64 = 65;
469 pub const SYS_SEMCTL: i64 = 66;
470 pub const SYS_SHMDT: i64 = 67;
471 pub const SYS_MSGGET: i64 = 68;
472 pub const SYS_MSGSND: i64 = 69;
473 pub const SYS_MSGRCV: i64 = 70;
474 pub const SYS_MSGCTL: i64 = 71;
475 pub const SYS_FCNTL: i64 = 72;
476 pub const SYS_FSYNC: i64 = 74;
477 pub const SYS_TRUNCATE: i64 = 76;
478 pub const SYS_FTRUNCATE: i64 = 77;
479 pub const SYS_GETCWD: i64 = 79;
480 pub const SYS_CHDIR: i64 = 80;
481 pub const SYS_SYMLINK: i64 = 88;
482 pub const SYS_FCHMOD: i64 = 91;
483 pub const SYS_UMASK: i64 = 95;
484 pub const SYS_GETRLIMIT: i64 = 97;
485 pub const SYS_SETUID: i64 = 105;
486 pub const SYS_SETGID: i64 = 106;
487 pub const SYS_SETPGID: i64 = 109;
488 pub const SYS_GETGROUPS: i64 = 115;
489 pub const SYS_GETPGID: i64 = 121;
490 pub const SYS_GETSID: i64 = 124;
491 pub const SYS_RT_SIGPENDING: i64 = 127;
492 pub const SYS_RT_SIGTIMEDWAIT: i64 = 128;
493 pub const SYS_RT_SIGSUSPEND: i64 = 130;
494 pub const SYS_SIGALTSTACK: i64 = 131;
495 pub const SYS_SETRLIMIT: i64 = 160;
496 pub const SYS_SETHOSTNAME: i64 = 170;
497 pub const SYS_FUTEX: i64 = 202;
498 pub const SYS_CLOCK_GETTIME: i64 = 228;
499 pub const SYS_CLOCK_GETRES: i64 = 229;
500 pub const SYS_CLOCK_NANOSLEEP: i64 = 230;
501 pub const SYS_EXIT_GROUP: i64 = 231;
502 pub const SYS_TGKILL: i64 = 234;
503 pub const SYS_MKDIRAT: i64 = 258;
504 pub const SYS_NEWFSTATAT: i64 = 262;
505 pub const SYS_UNLINKAT: i64 = 263;
506 pub const SYS_LINKAT: i64 = 265;
507 pub const SYS_SYMLINKAT: i64 = 266;
508 pub const SYS_READLINKAT: i64 = 267;
509 pub const SYS_FCHMODAT: i64 = 268;
510 pub const SYS_SET_ROBUST_LIST: i64 = 273;
511 pub const SYS_UTIMENSAT: i64 = 280;
512 pub const SYS_OPENAT: i64 = 257;
513 pub const SYS_FACCESSAT: i64 = 269;
514 pub const SYS_DUP3: i64 = 292;
515 pub const SYS_PIPE2: i64 = 293;
516 pub const SYS_SYNCFS: i64 = 306;
517 pub const SYS_RENAMEAT2: i64 = 316;
518 pub const SYS_STATFS: i64 = 137;
519 pub const SYS_FSTATFS: i64 = 138;
520 pub const SYS_FDATASYNC: i64 = 75;
521 pub const SYS_PAUSE: i64 = 34;
522 pub const SYS_GETPID: i64 = 39;
523 pub const SYS_FORK: i64 = 57;
524 pub const SYS_EXIT: i64 = 60;
525 pub const SYS_GETPPID: i64 = 110;
526 pub const SYS_SETSID: i64 = 112;
527 pub const SYS_SYNC: i64 = 162;
528 pub const SYS_GETUID: i64 = 102;
529 pub const SYS_GETGID: i64 = 104;
530 pub const SYS_GETEUID: i64 = 107;
531 pub const SYS_GETEGID: i64 = 108;
532 pub const SYS_GETTID: i64 = 186;
533 pub const SYS_CLOCK_SETTIME: i64 = 227;
534 pub const SYS_CLONE: i64 = 56;
535 pub const SYS_PPOLL: i64 = 271;
536 pub const SYS_PREAD64: i64 = 17;
537}
538#[cfg(target_arch = "aarch64")]
539mod sysnr {
540 pub const SYS_READ: i64 = 63;
541 pub const SYS_WRITE: i64 = 64;
542 pub const SYS_CLOSE: i64 = 57;
544 pub const SYS_FSTAT: i64 = 80;
546 pub const SYS_LSEEK: i64 = 62;
547 pub const SYS_MMAP: i64 = 222;
548 pub const SYS_MUNMAP: i64 = 215;
549 pub const SYS_RT_SIGACTION: i64 = 134;
550 pub const SYS_RT_SIGPROCMASK: i64 = 135;
551 pub const SYS_IOCTL: i64 = 29;
552 pub const SYS_SHMGET: i64 = 194;
554 pub const SYS_SHMAT: i64 = 196;
555 pub const SYS_SHMCTL: i64 = 195;
556 pub const SYS_DUP: i64 = 23;
557 pub const SYS_NANOSLEEP: i64 = 101;
558 pub const SYS_SETITIMER: i64 = 103;
559 pub const SYS_SOCKET: i64 = 198;
561 pub const SYS_CONNECT: i64 = 203;
562 pub const SYS_ACCEPT: i64 = 202;
563 pub const SYS_SENDTO: i64 = 206;
564 pub const SYS_RECVFROM: i64 = 207;
565 pub const SYS_SHUTDOWN: i64 = 210;
566 pub const SYS_BIND: i64 = 200;
567 pub const SYS_LISTEN: i64 = 201;
568 pub const SYS_GETSOCKNAME: i64 = 204;
569 pub const SYS_SOCKETPAIR: i64 = 199;
570 pub const SYS_SETSOCKOPT: i64 = 208;
571 pub const SYS_EXECVE: i64 = 221;
572 pub const SYS_WAIT4: i64 = 260;
573 pub const SYS_KILL: i64 = 129;
574 pub const SYS_UNAME: i64 = 160;
575 pub const SYS_SEMGET: i64 = 190;
576 pub const SYS_SEMOP: i64 = 193;
577 pub const SYS_SEMCTL: i64 = 191;
578 pub const SYS_SHMDT: i64 = 197;
579 pub const SYS_MSGGET: i64 = 186;
580 pub const SYS_MSGSND: i64 = 189;
581 pub const SYS_MSGRCV: i64 = 188;
582 pub const SYS_MSGCTL: i64 = 187;
583 pub const SYS_FCNTL: i64 = 25;
584 pub const SYS_FSYNC: i64 = 82;
585 pub const SYS_TRUNCATE: i64 = 45;
586 pub const SYS_FTRUNCATE: i64 = 46;
587 pub const SYS_GETCWD: i64 = 17;
588 pub const SYS_CHDIR: i64 = 49;
589 pub const SYS_FCHMOD: i64 = 52;
591 pub const SYS_UMASK: i64 = 166;
592 pub const SYS_GETRLIMIT: i64 = 163;
593 pub const SYS_SETUID: i64 = 146;
594 pub const SYS_SETGID: i64 = 144;
595 pub const SYS_SETPGID: i64 = 154;
596 pub const SYS_GETGROUPS: i64 = 158;
597 pub const SYS_GETPGID: i64 = 155;
598 pub const SYS_GETSID: i64 = 156;
599 pub const SYS_RT_SIGPENDING: i64 = 136;
600 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
601 pub const SYS_RT_SIGSUSPEND: i64 = 133;
602 pub const SYS_SIGALTSTACK: i64 = 132;
603 pub const SYS_SETRLIMIT: i64 = 164;
604 pub const SYS_SETHOSTNAME: i64 = 161;
605 pub const SYS_FUTEX: i64 = 98;
606 pub const SYS_CLOCK_GETTIME: i64 = 113;
607 pub const SYS_CLOCK_GETRES: i64 = 114;
608 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
609 pub const SYS_EXIT_GROUP: i64 = 94;
610 pub const SYS_TGKILL: i64 = 131;
611 pub const SYS_MKDIRAT: i64 = 34;
612 pub const SYS_NEWFSTATAT: i64 = 79;
613 pub const SYS_UNLINKAT: i64 = 35;
614 pub const SYS_LINKAT: i64 = 37;
615 pub const SYS_SYMLINKAT: i64 = 36;
616 pub const SYS_READLINKAT: i64 = 78;
617 pub const SYS_FCHMODAT: i64 = 53;
618 pub const SYS_SET_ROBUST_LIST: i64 = 99;
619 pub const SYS_UTIMENSAT: i64 = 88;
620 pub const SYS_OPENAT: i64 = 56;
621 pub const SYS_FACCESSAT: i64 = 48;
622 pub const SYS_DUP3: i64 = 24;
623 pub const SYS_PIPE2: i64 = 59;
624 pub const SYS_SYNCFS: i64 = 267;
625 pub const SYS_RENAMEAT2: i64 = 276;
626 pub const SYS_STATFS: i64 = 43;
627 pub const SYS_FSTATFS: i64 = 44;
628 pub const SYS_FDATASYNC: i64 = 83;
629 pub const SYS_GETPID: i64 = 172;
630 pub const SYS_EXIT: i64 = 93;
631 pub const SYS_GETPPID: i64 = 173;
632 pub const SYS_SETSID: i64 = 157;
633 pub const SYS_SYNC: i64 = 81;
634 pub const SYS_GETUID: i64 = 174;
635 pub const SYS_GETGID: i64 = 176;
636 pub const SYS_GETEUID: i64 = 175;
637 pub const SYS_GETEGID: i64 = 177;
638 pub const SYS_GETTID: i64 = 178;
639 pub const SYS_CLOCK_SETTIME: i64 = 112;
640 pub const SYS_CLONE: i64 = 220;
641 pub const SYS_PPOLL: i64 = 73;
642 pub const SYS_PREAD64: i64 = 67;
643}
644#[cfg(target_arch = "riscv64")]
646mod sysnr {
647 pub const SYS_READ: i64 = 63;
648 pub const SYS_WRITE: i64 = 64;
649 pub const SYS_CLOSE: i64 = 57;
650 pub const SYS_FSTAT: i64 = 80;
651 pub const SYS_LSEEK: i64 = 62;
652 pub const SYS_MMAP: i64 = 222;
653 pub const SYS_MUNMAP: i64 = 215;
654 pub const SYS_RT_SIGACTION: i64 = 134;
655 pub const SYS_RT_SIGPROCMASK: i64 = 135;
656 pub const SYS_IOCTL: i64 = 29;
657 pub const SYS_SHMGET: i64 = 194;
658 pub const SYS_SHMAT: i64 = 196;
659 pub const SYS_SHMCTL: i64 = 195;
660 pub const SYS_DUP: i64 = 23;
661 pub const SYS_NANOSLEEP: i64 = 101;
662 pub const SYS_SETITIMER: i64 = 103;
663 pub const SYS_SOCKET: i64 = 198;
664 pub const SYS_CONNECT: i64 = 203;
665 pub const SYS_ACCEPT: i64 = 202;
666 pub const SYS_SENDTO: i64 = 206;
667 pub const SYS_RECVFROM: i64 = 207;
668 pub const SYS_SHUTDOWN: i64 = 210;
669 pub const SYS_BIND: i64 = 200;
670 pub const SYS_LISTEN: i64 = 201;
671 pub const SYS_GETSOCKNAME: i64 = 204;
672 pub const SYS_SOCKETPAIR: i64 = 199;
673 pub const SYS_SETSOCKOPT: i64 = 208;
674 pub const SYS_EXECVE: i64 = 221;
675 pub const SYS_WAIT4: i64 = 260;
676 pub const SYS_KILL: i64 = 129;
677 pub const SYS_UNAME: i64 = 160;
678 pub const SYS_SEMGET: i64 = 190;
679 pub const SYS_SEMOP: i64 = 193;
680 pub const SYS_SEMCTL: i64 = 191;
681 pub const SYS_SHMDT: i64 = 197;
682 pub const SYS_MSGGET: i64 = 186;
683 pub const SYS_MSGSND: i64 = 189;
684 pub const SYS_MSGRCV: i64 = 188;
685 pub const SYS_MSGCTL: i64 = 187;
686 pub const SYS_FCNTL: i64 = 25;
687 pub const SYS_FSYNC: i64 = 82;
688 pub const SYS_TRUNCATE: i64 = 45;
689 pub const SYS_FTRUNCATE: i64 = 46;
690 pub const SYS_GETCWD: i64 = 17;
691 pub const SYS_CHDIR: i64 = 49;
692 pub const SYS_FCHMOD: i64 = 52;
693 pub const SYS_UMASK: i64 = 166;
694 pub const SYS_GETRLIMIT: i64 = 163;
695 pub const SYS_SETUID: i64 = 146;
696 pub const SYS_SETGID: i64 = 144;
697 pub const SYS_SETPGID: i64 = 154;
698 pub const SYS_GETGROUPS: i64 = 158;
699 pub const SYS_GETPGID: i64 = 155;
700 pub const SYS_GETSID: i64 = 156;
701 pub const SYS_RT_SIGPENDING: i64 = 136;
702 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
703 pub const SYS_RT_SIGSUSPEND: i64 = 133;
704 pub const SYS_SIGALTSTACK: i64 = 132;
705 pub const SYS_SETRLIMIT: i64 = 164;
706 pub const SYS_SETHOSTNAME: i64 = 161;
707 pub const SYS_FUTEX: i64 = 98;
708 pub const SYS_CLOCK_GETTIME: i64 = 113;
709 pub const SYS_CLOCK_GETRES: i64 = 114;
710 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
711 pub const SYS_EXIT_GROUP: i64 = 94;
712 pub const SYS_TGKILL: i64 = 131;
713 pub const SYS_MKDIRAT: i64 = 34;
714 pub const SYS_NEWFSTATAT: i64 = 79;
715 pub const SYS_UNLINKAT: i64 = 35;
716 pub const SYS_LINKAT: i64 = 37;
717 pub const SYS_SYMLINKAT: i64 = 36;
718 pub const SYS_READLINKAT: i64 = 78;
719 pub const SYS_FCHMODAT: i64 = 53;
720 pub const SYS_SET_ROBUST_LIST: i64 = 99;
721 pub const SYS_UTIMENSAT: i64 = 88;
722 pub const SYS_OPENAT: i64 = 56;
723 pub const SYS_FACCESSAT: i64 = 48;
724 pub const SYS_DUP3: i64 = 24;
725 pub const SYS_PIPE2: i64 = 59;
726 pub const SYS_SYNCFS: i64 = 267;
727 pub const SYS_RENAMEAT2: i64 = 276;
728 pub const SYS_STATFS: i64 = 43;
729 pub const SYS_FSTATFS: i64 = 44;
730 pub const SYS_FDATASYNC: i64 = 83;
731 pub const SYS_GETPID: i64 = 172;
732 pub const SYS_EXIT: i64 = 93;
733 pub const SYS_GETPPID: i64 = 173;
734 pub const SYS_SETSID: i64 = 157;
735 pub const SYS_SYNC: i64 = 81;
736 pub const SYS_GETUID: i64 = 174;
737 pub const SYS_GETGID: i64 = 176;
738 pub const SYS_GETEUID: i64 = 175;
739 pub const SYS_GETEGID: i64 = 177;
740 pub const SYS_GETTID: i64 = 178;
741 pub const SYS_CLOCK_SETTIME: i64 = 112;
742 pub const SYS_CLONE: i64 = 220;
743 pub const SYS_PPOLL: i64 = 73;
744 pub const SYS_PREAD64: i64 = 67;
745}
746pub use sysnr::*;
747
748#[inline]
753unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
754 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
755}
756
757#[inline]
758unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
759 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
760}
761
762#[inline]
763unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
764 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
765}
766
767#[inline]
768unsafe fn sys_close(fd: i64) {
769 let _ = <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64);
770}
771
772#[inline]
773unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
774 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
775}
776
777unsafe fn sys_mmap(
778 addr: *mut u8,
779 length: usize,
780 prot: i32,
781 flags: i32,
782 fd: i32,
783 offset: i64,
784) -> *mut u8 {
785 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
786 if result < 0 && result > -4096 {
787 ERRNO = (-result) as c_int;
788 return MMAP_FAILED;
789 }
790 result as *mut u8
791}
792
793unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
794 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
795}
796
797#[no_mangle]
802pub unsafe extern "C" fn strlen(s: *const c_char) -> usize {
803 let s = s as *const u8;
804 let mut len = 0;
805 while *s.add(len) != 0 {
806 len += 1;
807 }
808 len
809}
810
811#[no_mangle]
812pub unsafe extern "C" fn memcpy(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
813 let dst = dst as *mut u8;
814 let src = src as *const u8;
815 let mut i = 0;
816 while i < n {
817 *dst.add(i) = *src.add(i);
818 i += 1;
819 }
820 dst as *mut c_void
821}
822
823#[no_mangle]
824pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void {
825 let s = s as *mut u8;
826 let mut i = 0;
827 while i < n {
828 *s.add(i) = c as u8;
829 i += 1;
830 }
831 s as *mut c_void
832}
833
834#[no_mangle]
835pub unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
836 let dst = dst as *mut u8;
837 let src = src as *const u8;
838 if (dst as usize) < (src as usize) {
839 let mut i = 0;
840 while i < n {
841 *dst.add(i) = *src.add(i);
842 i += 1;
843 }
844 } else {
845 let mut i = n;
846 while i > 0 {
847 i -= 1;
848 *dst.add(i) = *src.add(i);
849 }
850 }
851 dst as *mut c_void
852}
853
854#[no_mangle]
855pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
856 let s1 = s1 as *const u8;
857 let s2 = s2 as *const u8;
858 let mut i = 0;
859 while i < n {
860 let a = *s1.add(i);
861 let b = *s2.add(i);
862 if a != b {
863 return a as c_int - b as c_int;
864 }
865 i += 1;
866 }
867 0
868}
869
870#[no_mangle]
871pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
872 memcmp(s1, s2, n)
873}
874
875#[no_mangle]
876pub unsafe extern "C" fn strcmp(s1: *const u8, s2: *const u8) -> c_int {
877 let mut i = 0;
878 loop {
879 let a = *s1.add(i);
880 let b = *s2.add(i);
881 if a != b {
882 return a as c_int - b as c_int;
883 }
884 if a == 0 {
885 return 0;
886 }
887 i += 1;
888 }
889}
890
891#[no_mangle]
892pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
893 let mut i = 0;
894 while i < n {
895 let a = *s1.add(i);
896 let b = *s2.add(i);
897 if a != b {
898 return a as c_int - b as c_int;
899 }
900 if a == 0 {
901 return 0;
902 }
903 i += 1;
904 }
905 0
906}
907
908#[no_mangle]
909pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
910 let mut i = 0;
911 loop {
912 let c = *src.add(i);
913 *dst.add(i) = c;
914 if c == 0 {
915 break;
916 }
917 i += 1;
918 }
919 dst
920}
921
922#[no_mangle]
923pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
924 let mut i = 0;
925 while i < n && *src.add(i) != 0 {
926 *dst.add(i) = *src.add(i);
927 i += 1;
928 }
929 while i < n {
930 *dst.add(i) = 0;
931 i += 1;
932 }
933 dst
934}
935
936#[no_mangle]
937pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
938 let mut i = 0;
939 while *dst.add(i) != 0 {
940 i += 1;
941 }
942 let mut j = 0;
943 loop {
944 let c = *src.add(j);
945 *dst.add(i + j) = c;
946 if c == 0 {
947 break;
948 }
949 j += 1;
950 }
951 dst
952}
953
954#[no_mangle]
955pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
956 let mut i = 0;
957 while *dst.add(i) != 0 {
958 i += 1;
959 }
960 let mut j = 0;
961 while j < n && *src.add(j) != 0 {
962 *dst.add(i + j) = *src.add(j);
963 j += 1;
964 }
965 *dst.add(i + j) = 0;
966 dst
967}
968
969#[no_mangle]
970pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
971 let l = strlen(src as *const c_char);
972 if n > 0 {
973 let c = if l < n { l } else { n - 1 };
974 core::ptr::copy_nonoverlapping(src, dst, c);
975 *dst.add(c) = 0;
976 }
977 l
978}
979
980#[no_mangle]
981pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
982 let dl = strlen(dst as *const c_char);
983 let sl = strlen(src as *const c_char);
984 if dl >= n { return n + sl; }
985 let c = if sl < n - dl { sl } else { n - dl - 1 };
986 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
987 *dst.add(dl + c) = 0;
988 dl + sl
989}
990
991#[no_mangle]
992pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
993 let target = c as u8;
994 let mut i = 0;
995 loop {
996 let ch = *s.add(i);
997 if ch == target {
998 return s.add(i) as *mut u8;
999 }
1000 if ch == 0 {
1001 return null_mut();
1002 }
1003 i += 1;
1004 }
1005}
1006
1007#[no_mangle]
1008pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
1009 let target = c as u8;
1010 let mut i = 0;
1011 let mut last: *mut u8 = null_mut();
1012 loop {
1013 let ch = *s.add(i);
1014 if ch == target {
1015 last = s.add(i) as *mut u8;
1016 }
1017 if ch == 0 {
1018 return last;
1019 }
1020 i += 1;
1021 }
1022}
1023
1024#[no_mangle]
1025pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
1026 let mut i = 0;
1027 while i < maxlen && *s.add(i) != 0 {
1028 i += 1;
1029 }
1030 i
1031}
1032
1033#[no_mangle]
1034pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
1035 let mut i = 0;
1036 loop {
1037 let c = *s.add(i);
1038 if c == 0 {
1039 return i;
1040 }
1041 let mut j = 0;
1042 loop {
1043 let r = *reject.add(j);
1044 if r == 0 {
1045 break;
1046 }
1047 if c == r {
1048 return i;
1049 }
1050 j += 1;
1051 }
1052 i += 1;
1053 }
1054}
1055
1056#[no_mangle]
1057pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
1058 let mut i = 0;
1059 loop {
1060 let c = *s.add(i);
1061 if c == 0 {
1062 return i;
1063 }
1064 let mut found = false;
1065 let mut j = 0;
1066 loop {
1067 let a = *accept.add(j);
1068 if a == 0 {
1069 break;
1070 }
1071 if c == a {
1072 found = true;
1073 break;
1074 }
1075 j += 1;
1076 }
1077 if !found {
1078 return i;
1079 }
1080 i += 1;
1081 }
1082}
1083
1084#[no_mangle]
1085pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
1086 let mut i = 0;
1087 loop {
1088 let c = *s.add(i);
1089 if c == 0 {
1090 return null_mut();
1091 }
1092 let mut j = 0;
1093 loop {
1094 let a = *accept.add(j);
1095 if a == 0 {
1096 break;
1097 }
1098 if c == a {
1099 return s.add(i) as *mut u8;
1100 }
1101 j += 1;
1102 }
1103 i += 1;
1104 }
1105}
1106
1107#[no_mangle]
1108pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
1109 if *needle == 0 {
1110 return haystack as *mut u8;
1111 }
1112 let mut i = 0;
1113 loop {
1114 let h = *haystack.add(i);
1115 if h == 0 {
1116 return null_mut();
1117 }
1118 if h == *needle {
1119 let mut j = 0;
1120 loop {
1121 let n = *needle.add(j);
1122 if n == 0 {
1123 return haystack.add(i) as *mut u8;
1124 }
1125 if *haystack.add(i + j) != n {
1126 break;
1127 }
1128 j += 1;
1129 }
1130 }
1131 i += 1;
1132 }
1133}
1134
1135#[no_mangle]
1136pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1137 let target = c as u8;
1138 let mut i = 0;
1139 while i < n {
1140 if *s.add(i) == target {
1141 return s.add(i) as *mut u8;
1142 }
1143 i += 1;
1144 }
1145 null_mut()
1146}
1147
1148#[no_mangle]
1149pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1150 let target = c as u8;
1151 let mut i = n;
1152 while i > 0 {
1153 i -= 1;
1154 if *s.add(i) == target {
1155 return s.add(i) as *mut u8;
1156 }
1157 }
1158 null_mut()
1159}
1160
1161#[no_mangle]
1162pub unsafe extern "C" fn memmem(
1163 haystack: *const c_void, haystacklen: usize,
1164 needle: *const c_void, needlelen: usize,
1165) -> *mut c_void {
1166 if needlelen == 0 { return haystack as *mut c_void; }
1167 if haystacklen < needlelen { return null_mut(); }
1168 let h = haystack as *const u8;
1169 let n = needle as *const u8;
1170 let last = haystacklen - needlelen;
1171 for i in 0..=last {
1172 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
1173 return h.add(i) as *mut c_void;
1174 }
1175 }
1176 null_mut()
1177}
1178
1179#[no_mangle]
1180pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
1181 static mut STATE: *mut u8 = core::ptr::null_mut();
1182 let mut p = if s.is_null() { STATE } else { s };
1183 if p.is_null() {
1184 return core::ptr::null_mut();
1185 }
1186 loop {
1187 let c = *p;
1188 if c == 0 {
1189 STATE = core::ptr::null_mut();
1190 return core::ptr::null_mut();
1191 }
1192 let mut is_delim = false;
1193 let mut i = 0;
1194 loop {
1195 let d = *delim.add(i);
1196 if d == 0 {
1197 break;
1198 }
1199 if c == d {
1200 is_delim = true;
1201 break;
1202 }
1203 i += 1;
1204 }
1205 if !is_delim {
1206 break;
1207 }
1208 p = p.add(1);
1209 }
1210 let start = p;
1211 loop {
1212 let c = *p;
1213 if c == 0 {
1214 STATE = core::ptr::null_mut();
1215 return start;
1216 }
1217 let mut is_delim = false;
1218 let mut i = 0;
1219 loop {
1220 let d = *delim.add(i);
1221 if d == 0 {
1222 break;
1223 }
1224 if c == d {
1225 is_delim = true;
1226 break;
1227 }
1228 i += 1;
1229 }
1230 if is_delim {
1231 *p = 0;
1232 STATE = p.add(1);
1233 return start;
1234 }
1235 p = p.add(1);
1236 }
1237}
1238
1239type SizeT = usize;
1244type SSizeT = isize;
1245type mode_t = c_uint;
1246type TimeT = c_long;
1247type ClockT = c_long;
1248type wchar_t = c_int;
1249type wint_t = c_uint;
1250type wctype_t = *const c_int;
1251type wctrans_t = *const c_int;
1252
1253const WEOF: wint_t = 0xffffffff;
1254
1255#[repr(C)]
1256pub struct tm {
1257 pub tm_sec: c_int,
1258 pub tm_min: c_int,
1259 pub tm_hour: c_int,
1260 pub tm_mday: c_int,
1261 pub tm_mon: c_int,
1262 pub tm_year: c_int,
1263 pub tm_wday: c_int,
1264 pub tm_yday: c_int,
1265 pub tm_isdst: c_int,
1266 pub tm_gmtoff: c_long,
1267 pub tm_zone: *const c_char,
1268}
1269
1270#[repr(C)]
1271pub struct timeval {
1272 pub tv_sec: TimeT,
1273 pub tv_usec: c_long,
1274}
1275
1276const CT_UPPER: u8 = 1 << 0;
1281const CT_LOWER: u8 = 1 << 1;
1282const CT_DIGIT: u8 = 1 << 2;
1283const CT_SPACE: u8 = 1 << 3;
1284const CT_PUNCT: u8 = 1 << 4;
1285const CT_CNTRL: u8 = 1 << 5;
1286const CT_BLANK: u8 = 1 << 6;
1287const CT_XDIGIT: u8 = 1 << 7;
1288
1289const CT_TABLE: [u8; 128] = {
1290 let mut t = [0u8; 128];
1291 let mut i = 0;
1292 while i < 128 {
1293 let c = i as u8;
1294 let mut flags = 0u8;
1295 if c >= b'A' && c <= b'Z' {
1296 flags |= CT_UPPER;
1297 }
1298 if c >= b'a' && c <= b'z' {
1299 flags |= CT_LOWER;
1300 }
1301 if c >= b'0' && c <= b'9' {
1302 flags |= CT_DIGIT;
1303 }
1304 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
1305 flags |= CT_SPACE;
1306 }
1307 if (c >= b'!' && c <= b'/')
1308 || (c >= b':' && c <= b'@')
1309 || (c >= b'[' && c <= b'`')
1310 || (c >= b'{' && c <= b'~')
1311 {
1312 flags |= CT_PUNCT;
1313 }
1314 if c < 0x20 || c == 0x7f {
1315 flags |= CT_CNTRL;
1316 }
1317 if c == b' ' || c == b'\t' {
1318 flags |= CT_BLANK;
1319 }
1320 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
1321 flags |= CT_XDIGIT;
1322 }
1323 t[i] = flags;
1324 i += 1;
1325 }
1326 t
1327};
1328
1329#[inline]
1330fn ct_flags(c: c_int) -> u8 {
1331 if c < 0 || c > 127 {
1332 0
1333 } else {
1334 CT_TABLE[c as usize]
1335 }
1336}
1337
1338#[no_mangle]
1339pub extern "C" fn isalnum(c: c_int) -> c_int {
1340 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
1341}
1342
1343#[no_mangle]
1344pub extern "C" fn isalpha(c: c_int) -> c_int {
1345 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
1346}
1347
1348#[no_mangle]
1349pub extern "C" fn isascii(c: c_int) -> c_int {
1350 ((c as u32) <= 127) as c_int
1351}
1352
1353#[no_mangle]
1354pub extern "C" fn isblank(c: c_int) -> c_int {
1355 (ct_flags(c) & CT_BLANK != 0) as c_int
1356}
1357
1358#[no_mangle]
1359pub extern "C" fn iscntrl(c: c_int) -> c_int {
1360 (ct_flags(c) & CT_CNTRL != 0) as c_int
1361}
1362
1363#[no_mangle]
1364pub extern "C" fn isdigit(c: c_int) -> c_int {
1365 (ct_flags(c) & CT_DIGIT != 0) as c_int
1366}
1367
1368#[no_mangle]
1369pub extern "C" fn isgraph(c: c_int) -> c_int {
1370 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
1371}
1372
1373#[no_mangle]
1374pub extern "C" fn islower(c: c_int) -> c_int {
1375 (ct_flags(c) & CT_LOWER != 0) as c_int
1376}
1377
1378#[no_mangle]
1379pub extern "C" fn isprint(c: c_int) -> c_int {
1380 let flags = ct_flags(c);
1381 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
1382}
1383
1384#[no_mangle]
1385pub extern "C" fn ispunct(c: c_int) -> c_int {
1386 (ct_flags(c) & CT_PUNCT != 0) as c_int
1387}
1388
1389#[no_mangle]
1390pub extern "C" fn isspace(c: c_int) -> c_int {
1391 (ct_flags(c) & CT_SPACE != 0) as c_int
1392}
1393
1394#[no_mangle]
1395pub extern "C" fn isupper(c: c_int) -> c_int {
1396 (ct_flags(c) & CT_UPPER != 0) as c_int
1397}
1398
1399#[no_mangle]
1400pub extern "C" fn isxdigit(c: c_int) -> c_int {
1401 (ct_flags(c) & CT_XDIGIT != 0) as c_int
1402}
1403
1404#[no_mangle]
1405pub extern "C" fn tolower(c: c_int) -> c_int {
1406 if (ct_flags(c) & CT_UPPER) != 0 {
1407 c + (b'a' as c_int - b'A' as c_int)
1408 } else {
1409 c
1410 }
1411}
1412
1413#[no_mangle]
1414pub extern "C" fn toupper(c: c_int) -> c_int {
1415 if (ct_flags(c) & CT_LOWER) != 0 {
1416 c - (b'a' as c_int - b'A' as c_int)
1417 } else {
1418 c
1419 }
1420}
1421
1422unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
1427 if c == 0 { return None; }
1428 let d = if c >= b'0' && c <= b'9' {
1429 c - b'0'
1430 } else if c >= b'a' && c <= b'z' {
1431 c - b'a' + 10
1432 } else if c >= b'A' && c <= b'Z' {
1433 c - b'A' + 10
1434 } else {
1435 return None;
1436 };
1437 if (d as c_int) < base {
1438 Some(d)
1439 } else {
1440 None
1441 }
1442}
1443
1444unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
1445 let mut p = s;
1446 if *base == 0 {
1447 if *p == b'0' {
1448 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1449 *base = 16;
1450 p = p.add(2);
1451 } else {
1452 *base = 8;
1453 }
1454 } else {
1455 *base = 10;
1456 }
1457 } else if *base == 16 {
1458 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1459 p = p.add(2);
1460 }
1461 }
1462 p
1463}
1464
1465unsafe fn strtox(
1466 s: *const c_char,
1467 endptr: *mut *mut c_char,
1468 mut base: c_int,
1469 pos_limit: u64,
1470 neg_limit: u64,
1471) -> (u64, bool, bool) {
1472 let s0 = s as *const u8;
1473 let mut p = s0;
1474 while isspace(*p as c_int) != 0 {
1475 p = p.add(1);
1476 }
1477
1478 if base < 0 || base == 1 || base > 36 {
1479 if !endptr.is_null() {
1480 *endptr = s as *mut c_char;
1481 }
1482 ERRNO = EINVAL;
1483 return (0, false, false);
1484 }
1485
1486 let mut neg = false;
1487 match *p {
1488 b'-' => { neg = true; p = p.add(1); }
1489 b'+' => p = p.add(1),
1490 _ => {}
1491 }
1492
1493 p = parse_prefix(p, &mut base);
1494
1495 let limit = if neg { neg_limit } else { pos_limit };
1496 let mut val: u64 = 0;
1497 let mut any = false;
1498 while let Some(d) = parse_digit(*p, base) {
1499 any = true;
1500 if val > (limit - d as u64) / base as u64 {
1501 while parse_digit(*p, base).is_some() { p = p.add(1); }
1502 if !endptr.is_null() { *endptr = p as *mut c_char; }
1503 ERRNO = ERANGE_VAL;
1504 return (limit, true, neg);
1505 }
1506 val = val * base as u64 + d as u64;
1507 p = p.add(1);
1508 }
1509
1510 if !endptr.is_null() {
1511 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
1512 }
1513 (val, false, neg)
1514}
1515
1516#[no_mangle]
1517pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
1518 let pos_limit = c_long::MAX as u64;
1519 let neg_limit = pos_limit.wrapping_add(1);
1520 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1521 if overflow {
1522 return if neg { c_long::MIN } else { c_long::MAX };
1523 }
1524 if neg { val.wrapping_neg() as c_long } else { val as c_long }
1525}
1526
1527#[no_mangle]
1528pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
1529 let limit = c_ulong::MAX as u64;
1530 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1531 if overflow {
1532 return c_ulong::MAX;
1533 }
1534 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
1535}
1536
1537#[no_mangle]
1538pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
1539 let pos_limit = c_longlong::MAX as u64;
1540 let neg_limit = pos_limit.wrapping_add(1);
1541 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1542 if overflow {
1543 return if neg { c_longlong::MIN } else { c_longlong::MAX };
1544 }
1545 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
1546}
1547
1548#[no_mangle]
1549pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
1550 let limit = c_ulonglong::MAX as u64;
1551 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1552 if overflow {
1553 return c_ulonglong::MAX;
1554 }
1555 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
1556}
1557
1558#[no_mangle]
1559pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
1560 strtol(s, core::ptr::null_mut(), 10) as c_int
1561}
1562
1563#[no_mangle]
1564pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
1565 strtol(s, core::ptr::null_mut(), 10)
1566}
1567
1568#[no_mangle]
1569pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
1570 strtoll(s, core::ptr::null_mut(), 10)
1571}
1572
1573#[no_mangle]
1574pub extern "C" fn abs(n: c_int) -> c_int {
1575 if n < 0 {
1576 -n
1577 } else {
1578 n
1579 }
1580}
1581
1582#[no_mangle]
1583pub extern "C" fn labs(n: c_long) -> c_long {
1584 if n < 0 {
1585 -n
1586 } else {
1587 n
1588 }
1589}
1590
1591#[no_mangle]
1592pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
1593 if n < 0 {
1594 -n
1595 } else {
1596 n
1597 }
1598}
1599
1600static mut RAND_STATE: c_uint = 1;
1601
1602#[no_mangle]
1603pub extern "C" fn srand(seed: c_uint) {
1604 unsafe {
1605 RAND_STATE = seed;
1606 }
1607}
1608
1609#[no_mangle]
1610pub extern "C" fn rand() -> c_int {
1611 unsafe {
1612 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
1613 ((RAND_STATE >> 16) & 0x7fff) as c_int
1614 }
1615}
1616
1617#[repr(C)]
1622pub struct div_t { pub quot: c_int, pub rem: c_int }
1623#[repr(C)]
1624pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
1625#[repr(C)]
1626pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
1627
1628#[no_mangle]
1629pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1630 div_t { quot: num / den, rem: num % den }
1631}
1632
1633#[no_mangle]
1634pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1635 ldiv_t { quot: num / den, rem: num % den }
1636}
1637
1638#[no_mangle]
1639pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1640 lldiv_t { quot: num / den, rem: num % den }
1641}
1642
1643type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1648
1649#[no_mangle]
1650pub unsafe extern "C" fn bsearch(
1651 key: *const c_void,
1652 base: *const c_void,
1653 nel: usize,
1654 width: usize,
1655 cmp: CmpFn,
1656) -> *mut c_void {
1657 let mut base = base as *const u8;
1658 let mut nel = nel;
1659 while nel > 0 {
1660 let trial = base.add(width * (nel / 2));
1661 let sign = cmp(key, trial as *const c_void);
1662 if sign < 0 {
1663 nel /= 2;
1664 } else if sign > 0 {
1665 base = trial.add(width);
1666 nel -= nel / 2 + 1;
1667 } else {
1668 return trial as *mut c_void;
1669 }
1670 }
1671 null_mut()
1672}
1673
1674pub const SA_RESTORER: c_ulong = 0x04000000;
1679
1680pub const SIG_DFL: usize = 0;
1681pub const SIG_IGN: usize = 1;
1682pub const SIG_ERR: usize = !0usize;
1683
1684pub const SIGHUP: c_int = 1;
1685pub const SIGINT: c_int = 2;
1686pub const SIGQUIT: c_int = 3;
1687pub const SIGILL: c_int = 4;
1688pub const SIGTRAP: c_int = 5;
1689pub const SIGABRT: c_int = 6;
1690pub const SIGIOT: c_int = 6;
1691pub const SIGBUS: c_int = 7;
1692pub const SIGFPE: c_int = 8;
1693pub const SIGKILL: c_int = 9;
1694pub const SIGUSR1: c_int = 10;
1695pub const SIGSEGV: c_int = 11;
1696pub const SIGUSR2: c_int = 12;
1697pub const SIGPIPE: c_int = 13;
1698pub const SIGALRM: c_int = 14;
1699pub const SIGTERM: c_int = 15;
1700pub const SIGSTKFLT: c_int = 16;
1701pub const SIGCHLD: c_int = 17;
1702pub const SIGCONT: c_int = 18;
1703pub const SIGSTOP: c_int = 19;
1704pub const SIGTSTP: c_int = 20;
1705pub const SIGTTIN: c_int = 21;
1706pub const SIGTTOU: c_int = 22;
1707pub const SIGURG: c_int = 23;
1708pub const SIGXCPU: c_int = 24;
1709pub const SIGXFSZ: c_int = 25;
1710pub const SIGVTALRM: c_int = 26;
1711pub const SIGPROF: c_int = 27;
1712pub const SIGWINCH: c_int = 28;
1713pub const SIGIO: c_int = 29;
1714pub const SIGPOLL: c_int = 29;
1715pub const SIGPWR: c_int = 30;
1716pub const SIGSYS: c_int = 31;
1717pub const SIGUNUSED: c_int = 31;
1718pub const _NSIG: c_int = 65;
1719
1720pub const SIG_BLOCK: c_int = 0;
1721pub const SIG_UNBLOCK: c_int = 1;
1722pub const SIG_SETMASK: c_int = 2;
1723
1724pub const SA_NOCLDSTOP: c_ulong = 1;
1725pub const SA_NOCLDWAIT: c_ulong = 2;
1726pub const SA_SIGINFO: c_ulong = 4;
1727pub const SA_ONSTACK: c_ulong = 0x08000000;
1728pub const SA_RESTART: c_ulong = 0x10000000;
1729pub const SA_NODEFER: c_ulong = 0x40000000;
1730pub const SA_RESETHAND: c_ulong = 0x80000000;
1731
1732pub const SS_ONSTACK: c_int = 1;
1733pub const SS_DISABLE: c_int = 2;
1734pub const MINSIGSTKSZ: usize = 2048;
1735pub const SIGSTKSZ: usize = 8192;
1736
1737pub const SI_USER: c_int = 0;
1738pub const SI_TKILL: c_int = -6;
1739
1740#[repr(C)]
1741pub struct timespec {
1742 pub tv_sec: c_long,
1743 pub tv_nsec: c_long,
1744}
1745
1746#[repr(C)]
1747pub struct siginfo_t {
1748 pub si_signo: c_int,
1749 pub si_errno: c_int,
1750 pub si_code: c_int,
1751 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1753}
1754
1755#[repr(C)]
1756pub struct stack_t {
1757 pub ss_sp: *mut c_void,
1758 pub ss_flags: c_int,
1759 pub ss_size: usize,
1760}
1761
1762#[repr(C)]
1763pub struct sigaction {
1764 pub sa_handler: usize,
1765 pub sa_flags: c_ulong,
1766 pub sa_restorer: usize,
1767 pub sa_mask: [c_ulong; 1],
1768}
1769
1770pub type SigSetT = c_ulong;
1771
1772#[cfg(target_arch = "x86_64")]
1773core::arch::global_asm!(
1774 ".global sig_restorer",
1775 ".type sig_restorer, @function",
1776 "sig_restorer:",
1777 "mov eax, 15",
1778 "syscall",
1779);
1780
1781#[cfg(target_arch = "aarch64")]
1782core::arch::global_asm!(
1783 ".global sig_restorer",
1784 ".type sig_restorer, @function",
1785 "sig_restorer:",
1786 "mov x8, #139",
1787 "svc #0",
1788);
1789
1790#[cfg(target_arch = "riscv64")]
1791core::arch::global_asm!(
1792 ".global sig_restorer",
1793 ".type sig_restorer, @function",
1794 "sig_restorer:",
1795 "li a7, 139",
1796 "ecall",
1797);
1798
1799extern "C" {
1800 fn sig_restorer();
1801}
1802
1803#[inline]
1804unsafe fn sys_rt_sigaction(sig: c_int,
1805 act: *const sigaction,
1806 oldact: *mut sigaction,
1807 sigsetsize: usize,) -> i64 {
1808 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
1809}
1810
1811#[inline]
1812unsafe fn sys_rt_sigprocmask(how: c_int,
1813 set: *const SigSetT,
1814 oldset: *mut SigSetT,
1815 sigsetsize: usize,) -> i64 {
1816 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
1817}
1818
1819#[inline]
1820unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
1821 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
1822}
1823
1824#[inline]
1825unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
1826 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
1827}
1828
1829#[inline]
1830unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
1831 info: *mut siginfo_t,
1832 timeout: *const timespec,
1833 sigsetsize: usize,) -> i64 {
1834 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
1835}
1836
1837#[inline]
1838unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
1839 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
1840}
1841
1842#[inline]
1843unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
1844 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
1845}
1846
1847const CLOCK_REALTIME: c_int = 0;
1848const CLOCK_MONOTONIC: c_int = 1;
1849
1850#[inline]
1851unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
1852 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
1853}
1854
1855#[no_mangle]
1856pub unsafe extern "C" fn clock_gettime(clockid: c_int, ts: *mut timespec) -> c_int {
1857 if sys_clock_gettime(clockid, ts) < 0 { -1 } else { 0 }
1858}
1859
1860#[no_mangle]
1861pub unsafe extern "C" fn sigprocmask(
1862 how: c_int,
1863 set: *const SigSetT,
1864 oldset: *mut SigSetT,
1865) -> c_int {
1866 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
1868 let filtered: SigSetT;
1869 let set_ptr: *const SigSetT = if set.is_null() {
1870 set
1871 } else {
1872 filtered = *set & !internal_mask;
1873 &filtered
1874 };
1875 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
1876 if !oldset.is_null() {
1877 *oldset &= !internal_mask;
1878 }
1879 if r < 0 { -1 } else { 0 }
1880}
1881
1882#[inline]
1883unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
1884 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
1885}
1886
1887#[inline]
1888unsafe fn sys_getpid() -> i64 {
1889 <Arch as Syscalls>::syscall0(SYS_GETPID)
1890}
1891
1892#[no_mangle]
1893pub unsafe extern "C" fn sigaction(
1894 signum: c_int,
1895 act: *const sigaction,
1896 oldact: *mut sigaction,
1897) -> c_int {
1898 let kact: sigaction;
1899 let act_ptr = if act.is_null() {
1900 core::ptr::null()
1901 } else {
1902 kact = sigaction {
1903 sa_handler: (*act).sa_handler,
1904 sa_flags: (*act).sa_flags | SA_RESTORER,
1905 sa_restorer: sig_restorer as *const () as usize,
1906 sa_mask: (*act).sa_mask,
1907 };
1908 &kact as *const sigaction
1909 };
1910 let r = sys_rt_sigaction(signum, act_ptr, oldact, core::mem::size_of::<SigSetT>());
1911 if r < 0 {
1912 ERRNO = (-r) as c_int;
1913 -1
1914 } else {
1915 0
1916 }
1917}
1918
1919#[no_mangle]
1920pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
1921 let act = sigaction {
1922 sa_handler: handler,
1923 sa_flags: SA_RESTORER,
1924 sa_restorer: sig_restorer as *const () as usize,
1925 sa_mask: [0],
1926 };
1927 let mut old = sigaction {
1928 sa_handler: 0,
1929 sa_flags: 0,
1930 sa_restorer: 0,
1931 sa_mask: [0],
1932 };
1933 if sigaction(signum, &act, &mut old) == -1 {
1934 SIG_ERR
1935 } else {
1936 old.sa_handler
1937 }
1938}
1939
1940#[no_mangle]
1941pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
1942 sys_kill(pid, sig) as c_int
1943}
1944
1945#[no_mangle]
1946pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
1947 if sys_tgkill(tgid, tid, sig) < 0 { -1 } else { 0 }
1948}
1949
1950#[no_mangle]
1951pub unsafe extern "C" fn getpid() -> c_int {
1952 sys_getpid() as c_int
1953}
1954
1955#[no_mangle]
1956pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
1957 if sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig) < 0 {
1958 -1
1959 } else {
1960 0
1961 }
1962}
1963
1964#[no_mangle]
1965pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
1966 *set = 0;
1967 0
1968}
1969
1970#[no_mangle]
1971pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
1972 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
1974 0
1975}
1976
1977#[no_mangle]
1978pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
1979 let s = (signum as c_uint).wrapping_sub(1);
1980 if s as usize >= 64 {
1981 ERRNO = EINVAL;
1982 return -1;
1983 }
1984 if signum >= 32 && signum < __libc_current_sigrtmin() {
1986 return 0;
1987 }
1988 *set |= 1u64 << s;
1989 0
1990}
1991
1992#[no_mangle]
1993pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
1994 let s = (signum as c_uint).wrapping_sub(1);
1995 if s as usize >= 64 {
1996 ERRNO = EINVAL;
1997 return -1;
1998 }
1999 if signum >= 32 && signum < __libc_current_sigrtmin() {
2001 return 0;
2002 }
2003 *set &= !(1u64 << s);
2004 0
2005}
2006
2007#[no_mangle]
2008pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2009 let s = (signum as c_uint).wrapping_sub(1);
2010 if s as usize >= 64 { return 0; }
2011 if signum >= 32 && signum < __libc_current_sigrtmin() {
2013 return 0;
2014 }
2015 ((*set & (1u64 << s)) != 0) as c_int
2016}
2017
2018#[no_mangle]
2019pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2020 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2021 if r < 0 {
2022 ERRNO = (-r) as c_int;
2023 return -1;
2024 }
2025 0
2026}
2027
2028#[no_mangle]
2029pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2030 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2031 if r < 0 {
2032 ERRNO = (-r) as c_int;
2033 }
2034 -1
2035}
2036
2037#[no_mangle]
2038pub unsafe extern "C" fn sigtimedwait(
2039 mask: *const SigSetT,
2040 info: *mut siginfo_t,
2041 timeout: *const timespec,
2042) -> c_int {
2043 loop {
2044 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2045 if r >= 0 {
2046 return r as c_int;
2047 }
2048 let e = (-r) as c_int;
2049 if e != EINTR {
2050 ERRNO = e;
2051 return -1;
2052 }
2053 }
2054}
2055
2056#[no_mangle]
2057pub unsafe extern "C" fn sigwaitinfo(
2058 mask: *const SigSetT,
2059 info: *mut siginfo_t,
2060) -> c_int {
2061 sigtimedwait(mask, info, core::ptr::null())
2062}
2063
2064#[no_mangle]
2065pub unsafe extern "C" fn sigwait(
2066 mask: *const SigSetT,
2067 sig: *mut c_int,
2068) -> c_int {
2069 let mut info: siginfo_t = core::mem::zeroed();
2070 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2071 return ERRNO;
2072 }
2073 *sig = info.si_signo;
2074 0
2075}
2076
2077#[no_mangle]
2078pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2079 if !ss.is_null() {
2080 if (*ss).ss_flags & SS_ONSTACK != 0 {
2081 ERRNO = EINVAL;
2082 return -1;
2083 }
2084 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2085 ERRNO = ENOMEM;
2086 return -1;
2087 }
2088 }
2089 let r = sys_sigaltstack(ss, old_ss);
2090 if r < 0 {
2091 ERRNO = (-r) as c_int;
2092 return -1;
2093 }
2094 0
2095}
2096
2097#[no_mangle]
2103#[inline(never)]
2104#[cfg(target_arch = "x86_64")]
2105pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2106 core::arch::asm!(
2107 "mov rax, [rsp]",
2108 "lea rcx, [rsp + 8]",
2109 "mov [r8], rbx",
2110 "mov [r8 + 8], rbp",
2111 "mov [r8 + 16], r12",
2112 "mov [r8 + 24], r13",
2113 "mov [r8 + 32], r14",
2114 "mov [r8 + 40], r15",
2115 "mov [r8 + 48], rcx",
2116 "mov [r8 + 56], rax",
2117 in("r8") env,
2118 lateout("rax") _,
2119 lateout("rcx") _,
2120 options(nostack),
2121 );
2122 0
2123}
2124
2125#[no_mangle]
2126#[inline(never)]
2127#[cfg(target_arch = "x86_64")]
2128pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2129 let ret = if val == 0 { 1 } else { val } as u32;
2130 core::arch::asm!(
2131 "mov rbx, [r8]",
2132 "mov rbp, [r8 + 8]",
2133 "mov r12, [r8 + 16]",
2134 "mov r13, [r8 + 24]",
2135 "mov r14, [r8 + 32]",
2136 "mov r15, [r8 + 40]",
2137 "mov rsp, [r8 + 48]",
2138 "mov eax, edx",
2139 "jmp [r8 + 56]",
2140 in("r8") env,
2141 in("edx") ret,
2142 options(noreturn),
2143 );
2144}
2145
2146#[no_mangle]
2147#[unsafe(naked)]
2148#[cfg(target_arch = "aarch64")]
2149pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2150 core::arch::naked_asm!(
2151 "stp x19, x20, [x0, #0]",
2152 "stp x21, x22, [x0, #16]",
2153 "stp x23, x24, [x0, #32]",
2154 "stp x25, x26, [x0, #48]",
2155 "stp x27, x28, [x0, #64]",
2156 "stp x29, x30, [x0, #80]",
2157 "mov x2, sp",
2158 "str x2, [x0, #104]",
2159 "stp d8, d9, [x0, #112]",
2160 "stp d10, d11, [x0, #128]",
2161 "stp d12, d13, [x0, #144]",
2162 "stp d14, d15, [x0, #160]",
2163 "mov x0, #0",
2164 "ret",
2165 );
2166}
2167
2168#[no_mangle]
2169#[inline(never)]
2170#[cfg(target_arch = "aarch64")]
2171pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2172 let ret = if val == 0 { 1 } else { val } as u64;
2173 core::arch::asm!(
2174 "ldp x19, x20, [x0]",
2175 "ldp x21, x22, [x0, #16]",
2176 "ldp x23, x24, [x0, #32]",
2177 "ldp x25, x26, [x0, #48]",
2178 "ldp x27, x28, [x0, #64]",
2179 "ldp x29, x30, [x0, #80]",
2180 "ldr x2, [x0, #104]",
2181 "mov sp, x2",
2182 "ldp d8, d9, [x0, #112]",
2183 "ldp d10, d11, [x0, #128]",
2184 "ldp d12, d13, [x0, #144]",
2185 "ldp d14, d15, [x0, #160]",
2186 "mov x0, x1",
2187 "br x30",
2188 in("x0") env,
2189 in("x1") ret,
2190 options(noreturn),
2191 );
2192}
2193
2194#[no_mangle]
2195#[unsafe(naked)]
2196#[cfg(target_arch = "riscv64")]
2197pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2198 core::arch::naked_asm!(
2199 "sd s0, 0(a0)",
2200 "sd s1, 8(a0)",
2201 "sd s2, 16(a0)",
2202 "sd s3, 24(a0)",
2203 "sd s4, 32(a0)",
2204 "sd s5, 40(a0)",
2205 "sd s6, 48(a0)",
2206 "sd s7, 56(a0)",
2207 "sd s8, 64(a0)",
2208 "sd s9, 72(a0)",
2209 "sd s10, 80(a0)",
2210 "sd s11, 88(a0)",
2211 "sd sp, 96(a0)",
2212 "sd ra, 104(a0)",
2213 "li a0, 0",
2214 "ret",
2215 );
2216}
2217
2218#[no_mangle]
2219#[inline(never)]
2220#[cfg(target_arch = "riscv64")]
2221pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2222 let ret = if val == 0 { 1 } else { val } as u64;
2223 core::arch::asm!(
2224 "ld s0, 0(a0)",
2225 "ld s1, 8(a0)",
2226 "ld s2, 16(a0)",
2227 "ld s3, 24(a0)",
2228 "ld s4, 32(a0)",
2229 "ld s5, 40(a0)",
2230 "ld s6, 48(a0)",
2231 "ld s7, 56(a0)",
2232 "ld s8, 64(a0)",
2233 "ld s9, 72(a0)",
2234 "ld s10, 80(a0)",
2235 "ld s11, 88(a0)",
2236 "ld sp, 96(a0)",
2237 "ld ra, 104(a0)",
2238 "mv a0, a1",
2239 "ret",
2240 in("a0") env,
2241 in("a1") ret,
2242 options(noreturn),
2243 );
2244}
2245
2246#[no_mangle]
2254#[unsafe(naked)]
2255#[cfg(target_arch = "x86_64")]
2256pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2257 core::arch::naked_asm!("jmp sigsetjmp_real");
2258}
2259
2260#[no_mangle]
2261#[unsafe(naked)]
2262#[cfg(target_arch = "x86_64")]
2263pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2264 core::arch::naked_asm!("jmp sigsetjmp_real");
2265}
2266
2267#[cfg(target_arch = "x86_64")]
2268core::arch::global_asm!(
2269 ".type sigsetjmp_real, @function",
2270 "sigsetjmp_real:",
2271 " test esi, esi",
2272 " jz 1f",
2273 " pop qword ptr [rdi + 64]",
2274 " mov qword ptr [rdi + 80], rbx",
2275 " push rbx",
2276 " mov rbx, rdi",
2277 " call setjmp",
2278 " push qword ptr [rbx + 64]",
2279 " mov rdi, rbx",
2280 " mov esi, eax",
2281 " mov rbx, qword ptr [rbx + 80]",
2282 " lea rdx, [rdi + 72]",
2283 " test esi, esi",
2284 " jz 2f",
2285 " mov rsi, rdx",
2286 " xor rdx, rdx",
2287 " mov edi, 2",
2288 " jmp 3f",
2289 "2:",
2290 " xor rsi, rsi",
2291 " mov edi, 2",
2292 "3:",
2293 " mov eax, 14",
2294 " mov r10d, 8",
2295 " syscall",
2296 " test esi, esi",
2297 " jnz 4f",
2298 " mov rax, 0xfffffffe7fffffff",
2299 " and qword ptr [rdx], rax",
2300 "4:",
2301 " mov eax, esi",
2302 " ret",
2303 "1:",
2304 " jmp setjmp",
2305);
2306
2307#[no_mangle]
2308#[inline(never)]
2309#[cfg(target_arch = "x86_64")]
2310pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2311 longjmp(env, val);
2312}
2313
2314#[no_mangle]
2315#[cfg(target_arch = "aarch64")]
2316pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2317 const SIG_SETMASK: c_int = 2;
2318 let ss = env.add(24) as *mut SigSetT;
2319 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2320 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2321 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2322 ret
2323}
2324
2325#[no_mangle]
2326#[unsafe(naked)]
2327#[cfg(target_arch = "aarch64")]
2328pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2329 core::arch::naked_asm!(
2330 "cbz w1, setjmp",
2331 "str x30, [x0, #176]",
2332 "str x19, [x0, #184]",
2333 "mov x19, x0",
2334 "bl setjmp",
2335 "mov w1, w0",
2336 "mov x0, x19",
2337 "ldr x30, [x0, #176]",
2338 "ldr x19, [x0, #184]",
2339 "b __sigsetjmp_tail",
2340 );
2341}
2342
2343#[no_mangle]
2344#[unsafe(naked)]
2345#[cfg(target_arch = "aarch64")]
2346pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2347 core::arch::naked_asm!(
2348 "cbz w1, setjmp",
2349 "str x30, [x0, #176]",
2350 "str x19, [x0, #184]",
2351 "mov x19, x0",
2352 "bl setjmp",
2353 "mov w1, w0",
2354 "mov x0, x19",
2355 "ldr x30, [x0, #176]",
2356 "ldr x19, [x0, #184]",
2357 "b __sigsetjmp_tail",
2358 );
2359}
2360
2361#[no_mangle]
2362#[inline(never)]
2363#[cfg(target_arch = "aarch64")]
2364pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2365 longjmp(env, val);
2366}
2367
2368#[no_mangle]
2369#[cfg(target_arch = "riscv64")]
2370pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2371 const SIG_SETMASK: c_int = 2;
2372 let ss = env.add(27) as *mut SigSetT;
2373 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2374 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2375 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2376 ret
2377}
2378
2379#[no_mangle]
2380#[unsafe(naked)]
2381#[cfg(target_arch = "riscv64")]
2382pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2383 core::arch::naked_asm!(
2384 "bnez a1, 1f",
2385 "tail setjmp",
2386 "1:",
2387 "sd ra, 208(a0)",
2388 "sd s0, 224(a0)",
2389 "mv s0, a0",
2390 "call setjmp",
2391 "mv a1, a0",
2392 "mv a0, s0",
2393 "ld s0, 224(a0)",
2394 "ld ra, 208(a0)",
2395 "tail __sigsetjmp_tail",
2396 );
2397}
2398
2399#[no_mangle]
2400#[unsafe(naked)]
2401#[cfg(target_arch = "riscv64")]
2402pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2403 core::arch::naked_asm!(
2404 "bnez a1, 1f",
2405 "tail setjmp",
2406 "1:",
2407 "sd ra, 208(a0)",
2408 "sd s0, 224(a0)",
2409 "mv s0, a0",
2410 "call setjmp",
2411 "mv a1, a0",
2412 "mv a0, s0",
2413 "ld s0, 224(a0)",
2414 "ld ra, 208(a0)",
2415 "tail __sigsetjmp_tail",
2416 );
2417}
2418
2419#[no_mangle]
2420#[inline(never)]
2421#[cfg(target_arch = "riscv64")]
2422pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2423 longjmp(env, val);
2424}
2425
2426#[inline]
2431unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2432 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2433}
2434
2435#[inline]
2436unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2437 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2438}
2439
2440#[inline]
2441unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2442 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2443}
2444
2445#[inline]
2446unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2447 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2448}
2449
2450#[inline]
2451unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2452 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2453}
2454
2455#[inline]
2460unsafe fn sys_fork() -> i64 {
2461 #[cfg(target_arch = "x86_64")]
2462 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2463 #[cfg(target_arch = "aarch64")]
2464 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2465 #[cfg(target_arch = "riscv64")]
2466 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2467}
2468
2469#[inline]
2470unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2471 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2472}
2473
2474#[inline]
2475unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2476 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2477}
2478
2479#[inline]
2480unsafe fn sys_getppid() -> i64 {
2481 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2482}
2483
2484#[inline]
2485unsafe fn sys_getuid() -> i64 {
2486 <Arch as Syscalls>::syscall0(SYS_GETUID)
2487}
2488
2489#[inline]
2490unsafe fn sys_getgid() -> i64 {
2491 <Arch as Syscalls>::syscall0(SYS_GETGID)
2492}
2493
2494#[inline]
2495unsafe fn sys_geteuid() -> i64 {
2496 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2497}
2498
2499#[inline]
2500unsafe fn sys_getegid() -> i64 {
2501 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2502}
2503
2504#[no_mangle]
2505pub unsafe extern "C" fn fork() -> c_int {
2506 __fork_handler(-1);
2507 let mut rlim: Rlimit = core::mem::zeroed();
2511 let nproc_limit = sys_getrlimit(RLIMIT_NPROC, &mut rlim as *mut _ as *mut u8);
2512 let nproc_limited = nproc_limit == 0
2513 && rlim.rlim_cur != RLIM_INFINITY
2514 && rlim.rlim_cur == 0;
2515 let ret = if nproc_limited {
2516 -EAGAIN as i64
2517 } else {
2518 sys_fork()
2519 };
2520 let errno_save = if ret < 0 { EAGAIN } else { ERRNO };
2521 if ret == 0 {
2522 __fork_handler(1);
2523 } else {
2524 __fork_handler(0);
2525 }
2526 if ret < 0 {
2527 ERRNO = errno_save;
2528 return -1;
2529 }
2530 ret as c_int
2531}
2532
2533#[no_mangle]
2534pub unsafe extern "C" fn execve(
2535 path: *const c_char,
2536 argv: *const *const c_char,
2537 envp: *const *const c_char,
2538) -> c_int {
2539 sys_execve(path, argv, envp) as c_int
2540}
2541
2542#[no_mangle]
2543pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
2544 sys_wait4(-1, status, 0, core::ptr::null_mut()) as c_int
2545}
2546
2547#[no_mangle]
2548pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2549 sys_wait4(pid, status, options, core::ptr::null_mut()) as c_int
2550}
2551
2552#[no_mangle]
2553pub unsafe extern "C" fn getppid() -> c_int {
2554 sys_getppid() as c_int
2555}
2556
2557#[no_mangle]
2558pub unsafe extern "C" fn getuid() -> c_uint {
2559 sys_getuid() as c_uint
2560}
2561
2562#[no_mangle]
2563pub unsafe extern "C" fn getgid() -> c_uint {
2564 sys_getgid() as c_uint
2565}
2566
2567#[no_mangle]
2568pub unsafe extern "C" fn geteuid() -> c_uint {
2569 sys_geteuid() as c_uint
2570}
2571
2572#[no_mangle]
2573pub unsafe extern "C" fn getegid() -> c_uint {
2574 sys_getegid() as c_uint
2575}
2576
2577#[no_mangle]
2579pub unsafe extern "C" fn vfork() -> c_int {
2580 sys_fork() as c_int
2581}
2582
2583#[no_mangle]
2584pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2585 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2586 argv[0] = arg;
2587 let mut n: usize = 1;
2588 loop {
2589 let a: *const c_char = args.next_arg();
2590 if a.is_null() { break; }
2591 if n >= 255 { return -1; }
2592 argv[n] = a;
2593 n += 1;
2594 }
2595 argv[n] = core::ptr::null();
2596 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2597}
2598
2599const SPAWN_FA_MAX: usize = 5;
2607
2608#[repr(C)]
2609pub struct posix_spawn_file_actions_t {
2610 __pad0: [c_int; 2],
2611 __actions: *mut c_void,
2612 __pad: [c_int; 16],
2613}
2614
2615#[repr(C)]
2616pub struct posix_spawnattr_t {
2617 __flags: c_int,
2618 __pgrp: c_int,
2619 __def: [c_ulong; 16],
2620 __mask: [c_ulong; 16],
2621 __prio: c_int,
2622 __pol: c_int,
2623 __fn: *mut c_void,
2624 __pad: [u8; 64 - core::mem::size_of::<*mut c_void>()],
2625}
2626
2627#[no_mangle]
2628pub unsafe extern "C" fn posix_spawn_file_actions_init(fa: *mut posix_spawn_file_actions_t) -> c_int {
2629 core::ptr::write_bytes(fa, 0, 1);
2630 0
2631}
2632
2633#[no_mangle]
2634pub unsafe extern "C" fn posix_spawn_file_actions_destroy(_fa: *mut posix_spawn_file_actions_t) -> c_int {
2635 0
2636}
2637
2638unsafe fn spawn_fa_add(fa: *mut posix_spawn_file_actions_t, action_type: c_int, fd: c_int, newfd: c_int) -> c_int {
2639 let count = (*fa).__pad0[0] as usize;
2640 if count >= SPAWN_FA_MAX { return ENOMEM; }
2641 let base = count * 3;
2642 (*fa).__pad[base] = action_type;
2643 (*fa).__pad[base + 1] = fd;
2644 (*fa).__pad[base + 2] = newfd;
2645 (*fa).__pad0[0] += 1;
2646 0
2647}
2648
2649#[no_mangle]
2650pub unsafe extern "C" fn posix_spawn_file_actions_addclose(fa: *mut posix_spawn_file_actions_t, fd: c_int) -> c_int {
2651 spawn_fa_add(fa, 0, fd, 0)
2652}
2653
2654#[no_mangle]
2655pub unsafe extern "C" fn posix_spawn_file_actions_adddup2(fa: *mut posix_spawn_file_actions_t, oldfd: c_int, newfd: c_int) -> c_int {
2656 spawn_fa_add(fa, 1, oldfd, newfd)
2657}
2658
2659unsafe fn spawn_apply_actions(fa: *const posix_spawn_file_actions_t) {
2660 if fa.is_null() { return; }
2661 let count = (*fa).__pad0[0] as usize;
2662 for i in 0..count {
2663 let base = i * 3;
2664 match (*fa).__pad[base] {
2665 0 => { sys_close((*fa).__pad[base + 1] as i64); }
2666 1 => { sys_dup2((*fa).__pad[base + 1], (*fa).__pad[base + 2]); }
2667 _ => {}
2668 }
2669 }
2670}
2671
2672unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2674 let flen = strlen(file as *const c_char);
2675 let f = file as *const u8;
2676 let mut has_slash = false;
2677 for i in 0..flen {
2678 if *f.add(i) == b'/' { has_slash = true; break; }
2679 }
2680 if has_slash {
2681 sys_execve(file, argv, envp);
2682 _exit(127);
2683 }
2684 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2685 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2686 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2687 let plen = strlen(p as *const c_char);
2688 let mut buf: [u8; 4096] = [0; 4096];
2689 let mut i: usize = 0;
2690 while i <= plen {
2691 let start = i;
2692 while i < plen && *p.add(i) != b':' { i += 1; }
2693 let dlen = i - start;
2694 if dlen > 0 && dlen + 1 + flen < 4096 {
2695 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2696 *buf.as_mut_ptr().add(dlen) = b'/';
2697 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2698 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2699 }
2701 i += 1; }
2703 _exit(127);
2704}
2705
2706#[no_mangle]
2707pub unsafe extern "C" fn posix_spawnp(
2708 pid: *mut c_int,
2709 file: *const c_char,
2710 fa: *const posix_spawn_file_actions_t,
2711 _attrp: *const posix_spawnattr_t,
2712 argv: *const *const c_char,
2713 envp: *const *const c_char,
2714) -> c_int {
2715 let child = sys_fork();
2716 if child < 0 {
2717 ERRNO = EAGAIN;
2718 return -1;
2719 }
2720 if child == 0 {
2721 spawn_apply_actions(fa);
2723 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2724 spawn_execvp(file, argv, actual_envp);
2725 }
2727 *pid = child as c_int;
2728 0
2729}
2730
2731#[no_mangle]
2732pub unsafe extern "C" fn posix_spawn(
2733 pid: *mut c_int,
2734 path: *const c_char,
2735 fa: *const posix_spawn_file_actions_t,
2736 attrp: *const posix_spawnattr_t,
2737 argv: *const *const c_char,
2738 envp: *const *const c_char,
2739) -> c_int {
2740 posix_spawnp(pid, path, fa, attrp, argv, envp)
2743}
2744
2745#[no_mangle]
2746pub unsafe extern "C" fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int {
2747 core::ptr::write_bytes(attr, 0, 1);
2748 0
2749}
2750
2751#[no_mangle]
2752pub unsafe extern "C" fn posix_spawnattr_destroy(_attr: *mut posix_spawnattr_t) -> c_int {
2753 0
2754}
2755
2756#[repr(C)]
2761pub struct Stat {
2762 pub st_dev: u64,
2763 pub st_ino: u64,
2764 pub st_nlink: u64,
2765 pub st_mode: u32,
2766 pub st_uid: u32,
2767 pub st_gid: u32,
2768 _pad0: u32,
2769 pub st_rdev: u64,
2770 pub st_size: i64,
2771 pub st_blksize: i64,
2772 pub st_blocks: i64,
2773 pub st_atim: timespec,
2774 pub st_mtim: timespec,
2775 pub st_ctim: timespec,
2776 _unused: [i64; 3],
2777}
2778
2779pub const S_IFMT: u32 = 0o170000;
2780pub const S_IFDIR: u32 = 0o040000;
2781pub const S_IFCHR: u32 = 0o020000;
2782pub const S_IFBLK: u32 = 0o060000;
2783pub const S_IFREG: u32 = 0o100000;
2784pub const S_IFLNK: u32 = 0o120000;
2785pub const S_IFIFO: u32 = 0o010000;
2786pub const S_IFSOCK: u32 = 0o140000;
2787
2788pub const AT_FDCWD: i32 = -100;
2789
2790#[no_mangle]
2791pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2792 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2793 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2794 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2795 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2796 }
2797 0
2798}
2799
2800#[no_mangle]
2801pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2802 let r = sys_fstat(fd, buf as *mut u8);
2803 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2804}
2805
2806#[repr(C)]
2811pub struct Rlimit {
2812 pub rlim_cur: u64,
2813 pub rlim_max: u64,
2814}
2815
2816pub const RLIMIT_NOFILE: c_int = 7;
2817pub const RLIMIT_STACK: c_int = 3;
2818pub const RLIMIT_DATA: c_int = 2;
2819pub const RLIMIT_AS: c_int = 9;
2820pub const RLIMIT_CPU: c_int = 0;
2821pub const RLIMIT_FSIZE: c_int = 1;
2822pub const RLIMIT_CORE: c_int = 4;
2823pub const RLIMIT_RSS: c_int = 5;
2824pub const RLIMIT_NPROC: c_int = 6;
2825pub const RLIMIT_MEMLOCK: c_int = 8;
2826pub const RLIMIT_LOCKS: c_int = 10;
2827pub const RLIMIT_SIGPENDING: c_int = 11;
2828pub const RLIMIT_MSGQUEUE: c_int = 12;
2829pub const RLIMIT_NICE: c_int = 13;
2830pub const RLIMIT_RTPRIO: c_int = 14;
2831pub const RLIMIT_RTTIME: c_int = 15;
2832pub const RLIM_INFINITY: u64 = !0u64;
2833
2834#[no_mangle]
2835pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
2836 let r = sys_getrlimit(resource, rlim as *mut u8);
2837 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2838}
2839
2840#[no_mangle]
2841pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
2842 let r = sys_setrlimit(resource, rlim as *const u8);
2843 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2844}
2845
2846#[no_mangle]
2851pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
2852 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
2853 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2854}
2855
2856#[no_mangle]
2857pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
2858 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
2859 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2860}
2861
2862pub const AF_UNIX: c_int = 1;
2867pub const AF_INET: c_int = 2;
2868pub const AF_INET6: c_int = 10;
2869
2870pub const SOCK_STREAM: c_int = 1;
2871pub const SOCK_DGRAM: c_int = 2;
2872
2873pub const SHUT_RD: c_int = 0;
2874pub const SHUT_WR: c_int = 1;
2875pub const SHUT_RDWR: c_int = 2;
2876
2877pub const SOL_SOCKET: c_int = 1;
2878pub const SO_REUSEADDR: c_int = 2;
2879
2880#[repr(C)]
2881pub struct sockaddr {
2882 pub sa_family: u16,
2883 pub sa_data: [u8; 14],
2884}
2885
2886#[inline]
2887unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
2888 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
2889}
2890
2891#[inline]
2892unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
2893 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
2894}
2895
2896#[inline]
2897unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
2898 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
2899}
2900
2901#[inline]
2902unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
2903 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
2904}
2905
2906#[inline]
2907unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
2908 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
2909}
2910
2911#[inline]
2912unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
2913 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
2914}
2915
2916#[inline]
2917unsafe fn sys_sendto(fd: c_int,
2918 buf: *const c_void,
2919 len: usize,
2920 flags: c_int,
2921 addr: *const sockaddr,
2922 addrlen: c_uint,) -> i64 {
2923 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
2924}
2925
2926#[inline]
2927unsafe fn sys_recvfrom(fd: c_int,
2928 buf: *mut c_void,
2929 len: usize,
2930 flags: c_int,
2931 addr: *mut sockaddr,
2932 addrlen: *mut c_uint,) -> i64 {
2933 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
2934}
2935
2936#[inline]
2937unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
2938 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
2939}
2940
2941#[inline]
2942unsafe fn sys_setsockopt(fd: c_int,
2943 level: c_int,
2944 optname: c_int,
2945 optval: *const c_void,
2946 optlen: c_uint,) -> i64 {
2947 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
2948}
2949
2950#[inline]
2951unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
2952 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
2953}
2954
2955#[no_mangle]
2956pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
2957 let r = sys_socket(domain, ty, protocol);
2958 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2959 r as c_int
2960}
2961
2962#[no_mangle]
2963pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
2964 let r = sys_socketpair(domain, ty, protocol, sv);
2965 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2966 0
2967}
2968
2969#[no_mangle]
2970pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
2971 let r = sys_bind(fd, addr, len);
2972 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2973 0
2974}
2975
2976#[no_mangle]
2977pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
2978 let r = sys_listen(fd, backlog);
2979 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2980 0
2981}
2982
2983#[no_mangle]
2984pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
2985 let r = sys_accept(fd, addr, len);
2986 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2987 r as c_int
2988}
2989
2990#[no_mangle]
2991pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
2992 let r = sys_connect(fd, addr, len);
2993 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2994 0
2995}
2996
2997#[no_mangle]
2998pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
2999 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3000 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3001 r as isize
3002}
3003
3004#[no_mangle]
3005pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3006 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3007 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3008 r as isize
3009}
3010
3011#[no_mangle]
3012pub unsafe extern "C" fn sendto(
3013 fd: c_int,
3014 buf: *const c_void,
3015 len: usize,
3016 flags: c_int,
3017 addr: *const sockaddr,
3018 addrlen: c_uint,
3019) -> isize {
3020 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3021 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3022 r as isize
3023}
3024
3025#[no_mangle]
3026pub unsafe extern "C" fn recvfrom(
3027 fd: c_int,
3028 buf: *mut c_void,
3029 len: usize,
3030 flags: c_int,
3031 addr: *mut sockaddr,
3032 addrlen: *mut c_uint,
3033) -> isize {
3034 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3035 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3036 r as isize
3037}
3038
3039#[no_mangle]
3040pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3041 sys_shutdown(fd, how) as c_int
3042}
3043
3044#[no_mangle]
3045pub unsafe extern "C" fn setsockopt(
3046 fd: c_int,
3047 level: c_int,
3048 optname: c_int,
3049 optval: *const c_void,
3050 optlen: c_uint,
3051) -> c_int {
3052 sys_setsockopt(fd, level, optname, optval, optlen) as c_int
3053}
3054
3055#[no_mangle]
3056pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3057 sys_getsockname(fd, addr, len) as c_int
3058}
3059
3060#[no_mangle]
3061pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3062 hostlong.to_be()
3063}
3064
3065#[no_mangle]
3066pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3067 c_uint::from_be(netlong)
3068}
3069
3070#[no_mangle]
3071pub extern "C" fn htons(hostshort: u16) -> u16 {
3072 hostshort.to_be()
3073}
3074
3075#[no_mangle]
3076pub extern "C" fn ntohs(netshort: u16) -> u16 {
3077 u16::from_be(netshort)
3078}
3079
3080pub type PthreadT = c_ulong;
3081
3082#[repr(C)]
3084pub struct pthread_attr_t {
3085 __i: [c_int; 14],
3086}
3087
3088#[repr(C)]
3091pub struct pthread_mutex_t {
3092 __i: [c_int; 10],
3093}
3094
3095#[repr(C)]
3096pub struct pthread_mutexattr_t {
3097 __attr: c_uint,
3098}
3099
3100#[repr(C)]
3103pub struct pthread_cond_t {
3104 __i: [c_int; 12],
3105}
3106
3107#[repr(C)]
3108pub struct pthread_condattr_t {
3109 __attr: c_uint,
3110}
3111
3112#[repr(C)]
3115pub struct pthread_rwlock_t {
3116 __i: [c_int; 14],
3117}
3118
3119#[repr(C)]
3120pub struct pthread_rwlockattr_t {
3121 __attr: [c_uint; 2],
3122}
3123
3124#[repr(C)]
3126pub struct pthread_barrier_t {
3127 __i: [c_int; 8],
3128}
3129
3130#[repr(C)]
3131pub struct pthread_barrierattr_t {
3132 __attr: c_uint,
3133}
3134
3135pub type pthread_spinlock_t = c_int;
3136pub type pthread_once_t = c_int;
3137pub type pthread_key_t = c_uint;
3138
3139#[repr(C)]
3141pub struct sem_t {
3142 __val: [c_int; 8],
3143}
3144
3145#[repr(C)]
3146pub struct sched_param {
3147 pub sched_priority: c_int,
3148}
3149
3150const CLONE_VM: c_ulong = 0x00000100;
3151const CLONE_FS: c_ulong = 0x00000200;
3152const CLONE_FILES: c_ulong = 0x00000400;
3153const CLONE_SIGHAND: c_ulong = 0x00000800;
3154const CLONE_THREAD: c_ulong = 0x00010000;
3155const CLONE_SYSVSEM: c_ulong = 0x00040000;
3156const CLONE_SETTLS: c_ulong = 0x00080000;
3157const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3158const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3159
3160const FUTEX_WAIT: c_int = 0;
3161const FUTEX_WAKE: c_int = 1;
3162const FUTEX_LOCK_PI: c_int = 6;
3163const FUTEX_UNLOCK_PI: c_int = 7;
3164const FUTEX_TRYLOCK_PI: c_int = 8;
3165
3166const SIGCANCEL: c_int = 32;
3168
3169const PTHREAD_MUTEX_NORMAL: c_int = 0;
3170const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3171const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3172const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3173
3174const PTHREAD_CREATE_JOINABLE: c_int = 0;
3175const PTHREAD_CREATE_DETACHED: c_int = 1;
3176
3177const PTHREAD_CANCEL_ENABLE: c_int = 0;
3178const PTHREAD_CANCEL_DISABLE: c_int = 1;
3179const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3180const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3181
3182const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3183const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3184const PTHREAD_PROCESS_SHARED: c_int = 1;
3185const PTHREAD_INHERIT_SCHED: c_int = 0;
3186const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3187
3188const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3189
3190const PTHREAD_KEYS_MAX: usize = 128;
3191const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3192const SEM_VALUE_MAX: c_int = 0x7fffffff;
3193
3194const DT_EXITED: c_int = 0;
3195const DT_EXITING: c_int = 1;
3196const DT_JOINABLE: c_int = 2;
3197const DT_DETACHED: c_int = 3;
3198
3199#[repr(C)]
3201#[derive(Copy, Clone)]
3202pub struct __ptcb {
3203 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3204 __x: *mut c_void,
3205 __next: *mut __ptcb,
3206}
3207
3208#[repr(C)]
3210#[derive(Copy, Clone)]
3211struct robust_list {
3212 next: *mut robust_list,
3213}
3214
3215#[repr(C)]
3216#[derive(Copy, Clone)]
3217struct robust_list_head {
3218 list: robust_list,
3219 futex_offset: c_long,
3220 pending: *mut robust_list,
3221}
3222
3223#[cfg(all(target_arch = "x86_64", not(test)))]
3225core::arch::global_asm!(
3226 ".global __rc_clone",
3227 ".type __rc_clone, @function",
3228 "__rc_clone:",
3229 "mov rax, rdi",
3230 "mov rdi, rdx",
3231 "mov rdx, r8",
3232 "mov r10, [rsp + 8]",
3233 "mov r8, r9",
3234 "mov r9, rax",
3235 "and rsi, -16",
3236 "sub rsi, 8",
3237 "mov [rsi], rcx",
3238 "mov eax, 56",
3239 "syscall",
3240 "test rax, rax",
3241 "jnz 1f",
3242 "pop rdi",
3243 "call r9",
3244 "hlt",
3245 "1:",
3246 "ret",
3247);
3248
3249#[no_mangle]
3251#[unsafe(naked)]
3252#[cfg(target_arch = "aarch64")]
3253pub unsafe extern "C" fn __rc_clone(
3254 fn_: usize,
3255 stack: *mut u8,
3256 flags: c_ulong,
3257 arg: *mut c_void,
3258 ptid: *mut c_int,
3259 tls: c_ulong,
3260 ctid: *mut c_int,
3261) -> i64 {
3262 core::arch::naked_asm!(
3263 "and x1, x1, #-16",
3264 "stp x0, x3, [x1, #-16]!",
3265 "uxtw x0, w2",
3266 "mov x2, x4",
3267 "mov x3, x5",
3268 "mov x4, x6",
3269 "mov x8, #220",
3270 "svc #0",
3271 "cbz x0, 1f",
3272 "ret",
3273 "1:",
3274 "mov x29, #0",
3275 "ldp x1, x0, [sp], #16",
3276 "blr x1",
3277 "mov x8, #93",
3278 "svc #0",
3279 );
3280}
3281
3282#[no_mangle]
3283#[unsafe(naked)]
3284#[cfg(target_arch = "riscv64")]
3285pub unsafe extern "C" fn __rc_clone(
3286 fn_: usize,
3287 stack: *mut u8,
3288 flags: c_ulong,
3289 arg: *mut c_void,
3290 ptid: *mut c_int,
3291 tls: c_ulong,
3292 ctid: *mut c_int,
3293) -> i64 {
3294 core::arch::naked_asm!(
3295 "andi a1, a1, -16",
3296 "addi a1, a1, -16",
3297 "sd a0, 0(a1)",
3298 "sd a3, 8(a1)",
3299 "mv a0, a2",
3300 "mv a2, a4",
3301 "mv a3, a5",
3302 "mv a4, a6",
3303 "li a7, 220",
3304 "ecall",
3305 "beqz a0, 1f",
3306 "ret",
3307 "1:",
3308 "ld a1, 0(sp)",
3309 "ld a0, 8(sp)",
3310 "jalr a1",
3311 "li a7, 93",
3312 "ecall",
3313 );
3314}
3315
3316#[cfg(all(target_arch = "x86_64", test))]
3317#[inline(never)]
3318unsafe fn __rc_clone(
3319 _fn_: usize,
3320 _stack: *mut u8,
3321 _flags: c_ulong,
3322 _arg: *mut c_void,
3323 _ptid: *mut c_int,
3324 _tls: c_ulong,
3325 _ctid: *mut c_int,
3326) -> i64 {
3327 -1
3328}
3329
3330#[cfg(all(target_arch = "x86_64", not(test)))]
3331extern "C" {
3332 fn __rc_clone(
3333 fn_: usize,
3334 stack: *mut u8,
3335 flags: c_ulong,
3336 arg: *mut c_void,
3337 ptid: *mut c_int,
3338 tls: c_ulong,
3339 ctid: *mut c_int,
3340 ) -> i64;
3341}
3342
3343#[inline(never)]
3344#[linkage = "weak"]
3345#[no_mangle]
3346pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3347 core::ptr::null_mut()
3348}
3349
3350#[inline(never)]
3351#[linkage = "weak"]
3352#[no_mangle]
3353pub extern "C" fn __rc_tls_block_size() -> usize {
3354 0
3355}
3356
3357#[inline(never)]
3358#[linkage = "weak"]
3359#[no_mangle]
3360pub extern "C" fn __rc_tls_base_offset() -> usize {
3361 0
3362}
3363
3364#[inline]
3365unsafe fn sys_gettid() -> i64 {
3366 <Arch as Syscalls>::syscall0(SYS_GETTID)
3367}
3368
3369#[inline]
3370unsafe fn sys_futex(uaddr: *mut c_int,
3371 futex_op: c_int,
3372 val: c_int,
3373 timeout: *mut c_void,
3374 uaddr2: *mut c_int,
3375 val3: c_int,) -> i64 {
3376 <Arch as Syscalls>::syscall6(SYS_FUTEX, uaddr as i64, futex_op as i64, val as i64, timeout as i64, uaddr2 as i64, val3 as i64)
3377}
3378
3379const MAX_THREADS: usize = 64;
3380const STACK_SIZE: usize = 1024 * 1024;
3381
3382#[repr(C)]
3383#[derive(Copy, Clone)]
3384struct Thread {
3385 tid: c_int,
3386 detach_state: c_int,
3387 result: *mut c_void,
3388 cancel: c_int,
3389 cancel_state: c_int,
3390 cancel_type: c_int,
3391 user_fn: usize,
3392 user_arg: *mut c_void,
3393 stack: *mut u8,
3394 stack_size: usize,
3395 fs_base: *mut u8,
3396 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3397 cancelbuf: *mut __ptcb,
3398 robust_list: robust_list_head,
3399}
3400
3401static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3402 tid: -1,
3403 detach_state: DT_JOINABLE,
3404 result: core::ptr::null_mut(),
3405 cancel: 0,
3406 cancel_state: PTHREAD_CANCEL_ENABLE,
3407 cancel_type: PTHREAD_CANCEL_DEFERRED,
3408 user_fn: 0,
3409 user_arg: core::ptr::null_mut(),
3410 stack: core::ptr::null_mut(),
3411 stack_size: 0,
3412 fs_base: core::ptr::null_mut(),
3413 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3414 cancelbuf: core::ptr::null_mut(),
3415 robust_list: robust_list_head {
3416 list: robust_list { next: core::ptr::null_mut() },
3417 futex_offset: 0,
3418 pending: core::ptr::null_mut(),
3419 },
3420}; MAX_THREADS];
3421static NEXT_SLOT: AtomicUsize = AtomicUsize::new(0);
3422static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3423static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3424
3425unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3427 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3428 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3429}
3430
3431unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3432 let c = if count < 0 { c_int::MAX } else { count };
3433 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3434}
3435
3436unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3437 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3438 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3439 if r < 0 { (-r) as c_int } else { 0 }
3440}
3441
3442unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3443 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3444 if r < 0 { (-r) as c_int } else { 0 }
3445}
3446
3447#[inline]
3448unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3449 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3450}
3451
3452unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3453 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3454 let mut now: timespec = core::mem::zeroed();
3455 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3456 let mut rel: timespec = core::mem::zeroed();
3457 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3458 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3459 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3460 if rel.tv_sec < 0 { return ETIMEDOUT; }
3461 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3462 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3463}
3464
3465unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3467 let a = &*(addr as *const AtomicI32);
3468 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3469 Ok(v) | Err(v) => v,
3470 }
3471}
3472
3473unsafe fn a_store(addr: *mut c_int, val: c_int) {
3474 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3475}
3476
3477unsafe fn a_load(addr: *const c_int) -> c_int {
3478 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3479}
3480
3481unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3482 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3483}
3484
3485unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3486 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3487}
3488
3489unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3490 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3491}
3492
3493unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3494 while a_swap(lock, 1) != 0 {
3495 let mut spins = 100;
3496 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3497 if a_load(lock) == 0 { continue; }
3498 a_fetch_add(waiters, 1);
3499 futex_wait(lock, 1);
3500 a_fetch_sub(waiters, 1);
3501 }
3502}
3503
3504unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3505 a_store(lock, 0);
3506 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3507}
3508
3509unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3510 let idx = NEXT_SLOT.fetch_add(1, Ordering::SeqCst);
3511 if idx >= MAX_THREADS { return None; }
3512 Some(&mut THREADS[idx])
3513}
3514
3515unsafe fn run_key_dtors(slot: &mut Thread) {
3516 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3517 let mut any = false;
3518 for i in 0..PTHREAD_KEYS_MAX {
3519 let val = slot.tsd[i];
3520 if !val.is_null() {
3521 if let Some(dtor) = KEY_DTORS[i] {
3522 slot.tsd[i] = core::ptr::null_mut();
3523 any = true;
3524 dtor(val);
3525 }
3526 }
3527 }
3528 if !any { break; }
3529 }
3530}
3531
3532unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3533 let slot = &mut *(slot as *mut Thread);
3534 let mut set: SigSetT = 0;
3535 sigemptyset(&mut set);
3536 sigaddset(&mut set, SIGCANCEL);
3537 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3538 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3539 core::mem::transmute::<usize, _>(slot.user_fn);
3540 let ret = user_fn(slot.user_arg);
3541 run_key_dtors(slot);
3542 slot.result = ret;
3543 a_store(&raw mut slot.detach_state, DT_EXITED);
3544 futex_wake(&raw mut slot.detach_state, 1);
3545 sys_exit_thread(0)
3546}
3547
3548unsafe fn find_thread() -> Option<&'static mut Thread> {
3549 let me = sys_gettid() as c_int;
3550 let base = core::ptr::addr_of_mut!(THREADS[0]);
3551 for i in 0..MAX_THREADS {
3552 let slot = base.add(i);
3553 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3554 return Some(&mut *slot);
3555 }
3556 }
3557 pthread_self();
3559 for i in 0..MAX_THREADS {
3560 let slot = base.add(i);
3561 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3562 return Some(&mut *slot);
3563 }
3564 }
3565 None
3566}
3567
3568#[no_mangle]
3569pub unsafe extern "C" fn pthread_self() -> PthreadT {
3570 let me = sys_gettid() as c_int;
3571 let base = core::ptr::addr_of_mut!(THREADS[0]);
3572 for i in 0..MAX_THREADS {
3573 let slot = base.add(i);
3574 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3575 return slot as PthreadT;
3576 }
3577 }
3578 let idx = NEXT_SLOT.fetch_add(1, Ordering::SeqCst);
3580 if idx < MAX_THREADS {
3581 let slot = &raw mut THREADS[idx];
3582 (*slot).tid = me;
3583 (*slot).detach_state = DT_JOINABLE;
3584 return slot as PthreadT;
3585 }
3586 0
3587}
3588
3589#[no_mangle]
3590pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3591 (t1 == t2) as c_int
3592}
3593
3594#[no_mangle]
3595pub unsafe extern "C" fn pthread_create(
3596 thread: *mut PthreadT,
3597 attr: *const pthread_attr_t,
3598 start_routine: usize,
3599 arg: *mut c_void,
3600) -> c_int {
3601 if start_routine == 0 || thread.is_null() { return EINVAL; }
3602 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3603 let slot = slot_ref as *mut Thread;
3604 let stack_size = if !attr.is_null() {
3605 let s = *((*attr).__i.as_ptr() as *const usize);
3606 if s > 0 { s } else { STACK_SIZE }
3607 } else { STACK_SIZE };
3608 let stack = sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
3609 if stack == MMAP_FAILED { return EAGAIN; }
3610 let fs_base = __rc_create_thread_tls();
3611 if fs_base.is_null() { sys_munmap(stack, stack_size); return EAGAIN; }
3612 (*slot).detach_state = DT_JOINABLE;
3613 (*slot).result = core::ptr::null_mut();
3614 (*slot).cancel = 0;
3615 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3616 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3617 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3618 (*slot).tid = 1;
3619 (*slot).user_fn = start_routine;
3620 (*slot).user_arg = arg;
3621 (*slot).stack = stack;
3622 (*slot).stack_size = stack_size;
3623 (*slot).fs_base = fs_base;
3624 let stack_top = stack.add(stack_size);
3625 let tid_ptr = &raw mut (*slot).tid;
3626 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3627 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3628 let tid = __rc_clone(thread_entry as *const () as usize, stack_top, flags, slot as *mut c_void, tid_ptr, fs_base as c_ulong, tid_ptr);
3629 if tid < 0 {
3630 (*slot).tid = -1;
3631 sys_munmap(stack, stack_size);
3632 sys_munmap(fs_base.sub(__rc_tls_base_offset()), __rc_tls_block_size());
3633 return EAGAIN;
3634 }
3635 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3636 (*slot).detach_state = DT_DETACHED;
3637 }
3638 *thread = slot as PthreadT;
3639 0
3640}
3641
3642#[no_mangle]
3643pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3644 let slot = thread as *mut Thread;
3645 if slot.is_null() { return EINVAL; }
3646 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3647 let tid_ptr = &raw mut (*slot).tid;
3648 loop {
3649 pthread_testcancel();
3650 let tid = core::ptr::read_volatile(tid_ptr);
3651 if tid == 0 { break; }
3652 if tid < 0 { return EINVAL; }
3653 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3654 pthread_testcancel();
3655 }
3656 if !retval.is_null() { *retval = (*slot).result; }
3657 let stack = (*slot).stack;
3658 let stack_size = (*slot).stack_size;
3659 let fs_base = (*slot).fs_base;
3660 (*slot).tid = -1;
3661 (*slot).detach_state = DT_JOINABLE;
3662 (*slot).result = core::ptr::null_mut();
3663 (*slot).stack = core::ptr::null_mut();
3664 (*slot).stack_size = 0;
3665 (*slot).fs_base = core::ptr::null_mut();
3666 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3667 if !fs_base.is_null() { let bs = __rc_tls_block_size(); let bo = __rc_tls_base_offset(); if bs > 0 { sys_munmap(fs_base.sub(bo), bs); } }
3668 0
3669}
3670
3671#[no_mangle]
3672pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3673 let slot = thread as *mut Thread;
3674 if slot.is_null() { return EINVAL; }
3675 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3676 if old == DT_EXITED {
3677 let stack = (*slot).stack;
3678 let stack_size = (*slot).stack_size;
3679 let fs_base = (*slot).fs_base;
3680 (*slot).tid = -1;
3681 (*slot).stack = core::ptr::null_mut();
3682 (*slot).stack_size = 0;
3683 (*slot).fs_base = core::ptr::null_mut();
3684 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3685 if !fs_base.is_null() { let bs = __rc_tls_block_size(); let bo = __rc_tls_base_offset(); sys_munmap(fs_base.sub(bo), bs); }
3686 }
3687 0
3688}
3689
3690#[no_mangle]
3691pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
3692 if let Some(slot) = find_thread() {
3693 run_cleanup_handlers(slot);
3694 run_key_dtors(slot);
3695 slot.result = retval;
3696 slot.detach_state = DT_EXITED;
3697 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
3698
3699 let mut active = 0usize;
3701 for i in 0..MAX_THREADS {
3702 if THREADS[i].tid > 0 {
3703 active += 1;
3704 }
3705 }
3706 if active == 1 {
3707 exit(0);
3708 }
3709 }
3710 sys_exit_thread(0);
3711}
3712
3713#[no_mangle]
3715pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
3716 core::ptr::write_bytes(attr, 0, 1);
3717 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
3718 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
3719 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
3720 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
3721 0
3722}
3723#[no_mangle]
3724pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
3725#[no_mangle]
3726pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
3727 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
3728 (*attr).__i[6] = s; 0
3729}
3730#[no_mangle]
3731pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
3732 *s = (*attr).__i[6]; 0
3733}
3734#[no_mangle]
3735pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3736 if sz < 16384 { return EINVAL; }
3737 *((*attr).__i.as_mut_ptr() as *mut usize) = sz; 0
3738}
3739#[no_mangle]
3740pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3741 *sz = *((*attr).__i.as_ptr() as *const usize); 0
3742}
3743#[no_mangle]
3744pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
3745 if sz < 16384 { return EINVAL; }
3746 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
3747 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = addr; 0
3748}
3749#[no_mangle]
3750pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
3751 *sz = *((*attr).__i.as_ptr() as *const usize);
3752 *addr = *((*attr).__i.as_ptr().add(4) as *const *mut c_void); 0
3753}
3754#[no_mangle]
3755pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3756 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
3757}
3758#[no_mangle]
3759pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3760 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
3761}
3762#[no_mangle]
3763pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
3764 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
3765 0
3766}
3767#[no_mangle]
3768pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
3769 *scope = PTHREAD_SCOPE_SYSTEM; 0
3770}
3771#[no_mangle]
3772pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
3773 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
3774 (*attr).__i[7] = inh; 0
3775}
3776#[no_mangle]
3777pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
3778 *inh = (*attr).__i[7]; 0
3779}
3780#[no_mangle]
3781pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
3782 (*attr).__i[8] = p; 0
3783}
3784#[no_mangle]
3785pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
3786 *p = (*attr).__i[8]; 0
3787}
3788#[no_mangle]
3789pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
3790 (*attr).__i[9] = (*param).sched_priority; 0
3791}
3792#[no_mangle]
3793pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
3794 (*param).sched_priority = (*attr).__i[9]; 0
3795}
3796
3797#[no_mangle]
3799pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
3800 (*attr).__attr = 0; 0
3801}
3802#[no_mangle]
3803pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
3804#[no_mangle]
3805pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
3806 if (t as c_uint) > 2 { return EINVAL; }
3807 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
3808}
3809#[no_mangle]
3810pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
3811 *t = ((*attr).__attr & 3) as c_int; 0
3812}
3813#[no_mangle]
3814pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
3815 if (p as c_uint) > 1 { return EINVAL; }
3816 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
3817}
3818#[no_mangle]
3819pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
3820 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
3821}
3822
3823#[no_mangle]
3824pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
3825 match protocol {
3826 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
3827 1 => {
3828 let mut lk: c_int = 0;
3829 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
3830 if r < 0 { return (-r) as c_int; }
3831 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3832 (*attr).__attr |= MUTEX_PI as c_uint;
3833 0
3834 }
3835 2 => ENOTSUP,
3836 _ => EINVAL,
3837 }
3838}
3839#[no_mangle]
3840pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
3841 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
3842}
3843
3844const ENOTSUP: c_int = 95;
3845
3846#[no_mangle]
3847pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
3848 if (robust as c_uint) > 1 { return EINVAL; }
3849 if robust != 0 {
3850 (*attr).__attr |= MUTEX_ROBUST as c_uint;
3851 } else {
3852 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
3853 }
3854 0
3855}
3856#[no_mangle]
3857pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
3858 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
3859}
3860
3861#[no_mangle]
3862pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
3863 let old = a_load(&raw const (*m).__i[1]);
3864 let own = old & 0x3fffffff;
3865 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
3866 return EINVAL;
3867 }
3868 let self_tid = sys_gettid() as c_int;
3869 if own != self_tid { return EPERM; }
3870 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
3871 0
3872}
3873
3874unsafe fn a_and(addr: *mut c_int, val: c_int) {
3875 let a = &*(addr as *const AtomicI32);
3876 a.fetch_and(val, Ordering::AcqRel);
3877}
3878
3879const MUTEX_TYPE_MASK: c_int = 3;
3881const MUTEX_ROBUST: c_int = 4;
3882const MUTEX_PI: c_int = 8;
3883const MUTEX_PSHARED: c_int = 128;
3884
3885unsafe fn ensure_robust_list(slot: &mut Thread) {
3886 if slot.robust_list.futex_offset == 0 {
3887 slot.robust_list.futex_offset = -28;
3888 slot.robust_list.pending = core::ptr::null_mut();
3889 sys_set_robust_list(&mut slot.robust_list, 24);
3890 }
3891}
3892
3893unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
3894 let type_ = (*m).__i[0];
3895 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
3897 return a_cas(&raw mut (*m).__i[1], 0, EBUSY) & EBUSY;
3898 }
3899 let base_type = type_ & MUTEX_TYPE_MASK;
3900 let self_tid = sys_gettid() as c_int;
3901 let old = a_load(&raw const (*m).__i[1]);
3902 let own = old & 0x3fffffff;
3903 if own == self_tid {
3904 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
3905 (*m).__i[5] = 0;
3906 return 0;
3907 }
3908 if base_type == PTHREAD_MUTEX_RECURSIVE {
3909 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
3910 (*m).__i[5] += 1;
3911 return 0;
3912 }
3913 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
3914 return EBUSY;
3915 }
3916 if own == 0x3fffffff { return ENOTRECOVERABLE; }
3917 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
3918 let mut newtid = self_tid;
3919 if (type_ & MUTEX_ROBUST) != 0 {
3920 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
3921 newtid |= old & 0x40000000;
3922 }
3923 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
3924 (*m).__i[5] = 0;
3925 if (type_ & MUTEX_ROBUST) != 0 {
3926 if let Some(slot) = find_thread() {
3927 ensure_robust_list(slot);
3928 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
3929 let head = &mut slot.robust_list.list;
3930 (*m_next).next = head.next;
3931 head.next = m_next;
3932 }
3933 }
3934 if old != 0 { return EOWNERDEAD; }
3935 0
3936 } else { EBUSY }
3937}
3938
3939unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
3940 let type_ = (*m).__i[0];
3941 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
3942 return 0;
3943 }
3944 let r = mutex_trylock(m);
3945 if r != EBUSY { return r; }
3946 if (type_ & MUTEX_PI) != 0 {
3947 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
3948 loop {
3949 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
3950 match e {
3951 0 => {
3952 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
3953 (*m).__i[5] = -1;
3954 let _ = mutex_trylock(m);
3955 return EOWNERDEAD;
3956 }
3957 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
3958 (*m).__i[2] = -1;
3959 futex_unlock_pi(&raw mut (*m).__i[1]);
3960 return EBUSY;
3961 }
3962 (*m).__i[5] = -1;
3963 let r2 = mutex_trylock(m);
3964 if r2 == 0 { return 0; }
3965 return r2;
3966 }
3967 EINTR => continue,
3968 EDEADLK => {
3969 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
3970 loop { pause(); }
3971 }
3972 EOWNERDEAD => {
3973 (*m).__i[5] = -1;
3974 let _ = mutex_trylock(m);
3975 return EOWNERDEAD;
3976 }
3977 _ => return e,
3978 }
3979 }
3980 }
3981 let mut spins = 100;
3982 while spins > 0 {
3983 let r = mutex_trylock(m);
3984 if r != EBUSY { return r; }
3985 core::hint::spin_loop();
3986 spins -= 1;
3987 }
3988 loop {
3989 let r = mutex_trylock(m);
3990 if r != EBUSY { return r; }
3991 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
3992 let self_tid = sys_gettid() as c_int;
3993 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
3994 }
3995 a_fetch_add(&raw mut (*m).__i[2], 1);
3996 let val = a_load(&raw const (*m).__i[1]);
3997 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
3998 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
3999 a_fetch_sub(&raw mut (*m).__i[2], 1);
4000 if e != 0 && e != EINTR { return e; }
4001 }
4002}
4003
4004#[no_mangle]
4005pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4006 core::ptr::write_bytes(mutex, 0, 1);
4007 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4008 0
4009}
4010#[no_mangle]
4011pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4012#[no_mangle]
4013pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4014 mutex_lock_internal(mutex, core::ptr::null())
4015}
4016#[no_mangle]
4017pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4018 mutex_trylock(mutex)
4019}
4020#[no_mangle]
4021pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4022 mutex_lock_internal(mutex, abs_timeout)
4023}
4024#[no_mangle]
4025pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4026 let type_ = (*mutex).__i[0];
4027 let base_type = type_ & MUTEX_TYPE_MASK;
4028 let old = a_load(&raw const (*mutex).__i[1]);
4029 if base_type != PTHREAD_MUTEX_NORMAL {
4030 let self_tid = sys_gettid() as c_int;
4031 if (old & 0x3fffffff) != self_tid { return EPERM; }
4032 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4033 (*mutex).__i[5] -= 1;
4034 return 0;
4035 }
4036 }
4037 let mut new = 0;
4038 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4039 new = 0x7fffffff;
4040 }
4041 if (type_ & MUTEX_PI) != 0 {
4042 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4043 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4044 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4045 }
4046 return 0;
4047 }
4048 a_store(&raw mut (*mutex).__i[1], new);
4049 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4050 futex_wake(&raw mut (*mutex).__i[1], 1);
4051 }
4052 0
4053}
4054
4055#[no_mangle]
4057pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4058 (*attr).__attr = 0; 0
4059}
4060#[no_mangle]
4061pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4062#[no_mangle]
4063pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4064 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4065 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4066}
4067#[no_mangle]
4068pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4069 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4070}
4071#[no_mangle]
4072pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4073 if (p as c_uint) > 1 { return EINVAL; }
4074 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4075}
4076#[no_mangle]
4077pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4078 *p = ((*attr).__attr >> 31) as c_int; 0
4079}
4080
4081#[no_mangle]
4083pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4084 core::ptr::write_bytes(cond, 0, 1);
4085 if !attr.is_null() {
4086 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4087 }
4088 0
4089}
4090#[no_mangle]
4091pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4092#[no_mangle]
4093pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4094 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4095}
4096#[no_mangle]
4097pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4098 pthread_testcancel();
4099 let seq_ptr = &raw mut (*cond).__i[2];
4100 let waiters_ptr = &raw mut (*cond).__i[3];
4101 let seq = a_load(seq_ptr);
4102 a_fetch_add(waiters_ptr, 1);
4103 pthread_mutex_unlock(mutex);
4104 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4105 a_fetch_sub(waiters_ptr, 1);
4106 let r = pthread_mutex_lock(mutex);
4107 if r != 0 { return r; }
4108 if e == EINTR {
4109 pthread_testcancel();
4110 }
4111 if e != 0 && e != EINTR { return e; }
4112 0
4113}
4114#[no_mangle]
4115pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4116 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4117 a_fetch_add(&raw mut (*cond).__i[2], 1);
4118 futex_wake(&raw mut (*cond).__i[2], 1);
4119 0
4120}
4121#[no_mangle]
4122pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4123 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4124 a_fetch_add(&raw mut (*cond).__i[2], 1);
4125 futex_wake(&raw mut (*cond).__i[2], -1);
4126 0
4127}
4128
4129#[no_mangle]
4131pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4132 (*attr).__attr = [0; 2]; 0
4133}
4134#[no_mangle]
4135pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4136#[no_mangle]
4137pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4138 if (p as c_uint) > 1 { return EINVAL; }
4139 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4140}
4141#[no_mangle]
4142pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4143 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4144}
4145
4146unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4148 loop {
4149 let val = a_load(&raw const (*rw).__i[0]);
4150 let cnt = val & 0x7fffffff;
4151 if cnt == 0x7fffffff { return EBUSY; }
4152 if cnt == 0x7ffffffe { return EAGAIN; }
4153 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4154 }
4155}
4156unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4157 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4158}
4159unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4160 let r = rwlock_tryrdlock(rw);
4161 if r != EBUSY { return r; }
4162 let mut spins = 100;
4163 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4164 loop {
4165 let r = rwlock_tryrdlock(rw);
4166 if r != EBUSY { return r; }
4167 let val = a_load(&raw const (*rw).__i[0]);
4168 if val & 0x7fffffff != 0x7fffffff { continue; }
4169 a_fetch_add(&raw mut (*rw).__i[1], 1);
4170 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4171 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4172 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4173 if e != 0 && e != EINTR { return e; }
4174 }
4175}
4176unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4177 let r = rwlock_trywrlock(rw);
4178 if r != EBUSY { return r; }
4179 let mut spins = 100;
4180 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4181 loop {
4182 let r = rwlock_trywrlock(rw);
4183 if r != EBUSY { return r; }
4184 let val = a_load(&raw const (*rw).__i[0]);
4185 if val == 0 { continue; }
4186 a_fetch_add(&raw mut (*rw).__i[1], 1);
4187 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4188 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4189 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4190 if e != 0 && e != EINTR { return e; }
4191 }
4192}
4193
4194#[no_mangle]
4195pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4196 core::ptr::write_bytes(rw, 0, 1);
4197 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4198 0
4199}
4200#[no_mangle]
4201pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4202#[no_mangle]
4203pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4204#[no_mangle]
4205pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4206#[no_mangle]
4207pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4208#[no_mangle]
4209pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4210#[no_mangle]
4211pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4212#[no_mangle]
4213pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4214#[no_mangle]
4215pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4216 loop {
4217 let val = a_load(&raw const (*rw).__i[0]);
4218 let cnt = val & 0x7fffffff;
4219 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4220 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4221 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4222 futex_wake(&raw mut (*rw).__i[0], cnt);
4223 }
4224 return 0;
4225 }
4226 }
4227}
4228
4229#[no_mangle]
4231pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4232#[no_mangle]
4233pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4234#[no_mangle]
4235pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4236 if (p as c_uint) > 1 { return EINVAL; }
4237 (*attr).__attr = p as c_uint; 0
4238}
4239#[no_mangle]
4240pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4241 *p = (*attr).__attr as c_int; 0
4242}
4243
4244#[no_mangle]
4246pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4247 if count == 0 { return EINVAL; }
4248 core::ptr::write_bytes(b, 0, 1);
4249 (*b).__i[2] = count as c_int - 1;
4250 0
4251}
4252#[no_mangle]
4253pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4254#[no_mangle]
4255pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4256 let limit = (*b).__i[2];
4257 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4258 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4259 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4260 a_store(&raw mut (*b).__i[3], arrived);
4261 if arrived > limit {
4262 a_store(&raw mut (*b).__i[3], 0);
4263 let gen = a_load(&raw const (*b).__i[4]);
4264 a_store(&raw mut (*b).__i[4], gen + 1);
4265 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4266 futex_wake(&raw mut (*b).__i[4], -1);
4267 return PTHREAD_BARRIER_SERIAL_THREAD;
4268 }
4269 let gen = a_load(&raw const (*b).__i[4]);
4270 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4271 while a_load(&raw const (*b).__i[4]) == gen {
4272 futex_wait(&raw mut (*b).__i[4], gen);
4273 }
4274 0
4275}
4276
4277#[no_mangle]
4279pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4280#[no_mangle]
4281pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4282#[no_mangle]
4283pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4284 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4285 0
4286}
4287#[no_mangle]
4288pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4289#[no_mangle]
4290pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4291
4292#[no_mangle]
4294pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4295 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4296 (*sem).__val[0] = value as c_int;
4297 (*sem).__val[1] = 0;
4298 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4299 0
4300}
4301#[no_mangle]
4302pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4303
4304unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4305 loop {
4306 let val = a_load(&raw const (*sem).__val[0]);
4307 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4308 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4309 }
4310}
4311
4312#[no_mangle]
4313pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4314 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO = EAGAIN; -1 }
4315}
4316#[no_mangle]
4317pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4318 pthread_testcancel();
4319 if sem_trywait_internal(sem) == 0 { return 0; }
4320 let mut spins = 100;
4321 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4322 loop {
4323 pthread_testcancel();
4324 if sem_trywait_internal(sem) == 0 { return 0; }
4325 let val = a_load(&raw const (*sem).__val[0]);
4326 if val & SEM_VALUE_MAX != 0 { continue; }
4327 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4328 a_fetch_add(&raw mut (*sem).__val[1], 1);
4329 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4330 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4331 }
4332}
4333#[no_mangle]
4334pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4335 pthread_testcancel();
4336 if sem_trywait_internal(sem) == 0 { return 0; }
4337 let mut spins = 100;
4338 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4339 loop {
4340 pthread_testcancel();
4341 if sem_trywait_internal(sem) == 0 { return 0; }
4342 let val = a_load(&raw const (*sem).__val[0]);
4343 if val & SEM_VALUE_MAX != 0 { continue; }
4344 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4345 a_fetch_add(&raw mut (*sem).__val[1], 1);
4346 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4347 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4348 if e != 0 && e != EINTR { ERRNO = e; return -1; }
4349 }
4350}
4351#[no_mangle]
4352pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4353 loop {
4354 let val = a_load(&raw const (*sem).__val[0]);
4355 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO = EOVERFLOW; return -1; }
4356 let mut new = val + 1;
4357 let waiters = a_load(&raw const (*sem).__val[1]);
4358 if waiters <= 1 { new &= !(1i32 << 31); }
4359 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4360 if val < 0 || waiters > 0 {
4361 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4362 }
4363 return 0;
4364 }
4365 }
4366}
4367#[no_mangle]
4368pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4369 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4370 0
4371}
4372
4373const NAME_MAX: usize = 255;
4378const SEM_NSEMS_MAX: usize = 256;
4379
4380static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4382
4383struct SemEntry {
4384 ino: u64,
4385 sem: *mut sem_t,
4386 refcnt: u32,
4387}
4388
4389static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4391 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4392 [ZERO; SEM_NSEMS_MAX]
4393};
4394
4395unsafe fn semtab_lock() {
4396 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4397 core::hint::spin_loop();
4398 }
4399}
4400
4401unsafe fn semtab_unlock() {
4402 SEMTAB_LOCK.store(0, Ordering::Release);
4403}
4404
4405unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4408 let mut p = name;
4409 while *p == b'/' as c_char { p = p.add(1); }
4411 let start = p;
4412 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4414 let len = p.offset_from(start) as usize;
4415 if len == 0 || *p != 0 {
4417 ERRNO = EINVAL;
4418 return -1;
4419 }
4420 if len == 1 && *start == b'.' as c_char {
4421 ERRNO = EINVAL;
4422 return -1;
4423 }
4424 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4425 ERRNO = EINVAL;
4426 return -1;
4427 }
4428 if len > NAME_MAX {
4429 ERRNO = ENAMETOOLONG;
4430 return -1;
4431 }
4432 let prefix = b"/dev/shm/\0";
4434 let mut i = 0;
4435 while prefix[i] != 0 {
4436 *buf.add(i) = prefix[i];
4437 i += 1;
4438 }
4439 let mut j = 0;
4440 while j < len {
4441 *buf.add(i + j) = *start.add(j) as u8;
4442 j += 1;
4443 }
4444 *buf.add(i + j) = 0;
4445 (i + j) as c_int
4446}
4447
4448#[no_mangle]
4449pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4450 let mut buf = [0u8; 16 + NAME_MAX + 1];
4451 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4452 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4453 if fd < 0 { ERRNO = (-fd) as c_int; return -1; }
4454 fd as c_int
4455}
4456
4457#[no_mangle]
4458pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4459 let mut buf = [0u8; 16 + NAME_MAX + 1];
4460 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4461 let r = sys_unlink(buf.as_ptr());
4462 if r < 0 { ERRNO = (-r) as c_int; return -1; }
4463 0
4464}
4465
4466#[no_mangle]
4467pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4468 let mut buf = [0u8; 16 + NAME_MAX + 1];
4469 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4470 return core::ptr::null_mut(); }
4472
4473 let oflags = flags & (O_CREAT | O_EXCL);
4474
4475 semtab_lock();
4476
4477 let mut slot: c_int = -1;
4479 for i in 0..SEMTAB_LEN {
4480 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4481 }
4482 if slot < 0 {
4483 ERRNO = EMFILE;
4484 semtab_unlock();
4485 return core::ptr::null_mut();
4486 }
4487 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4490
4491 let mut mode: mode_t = 0;
4493 let mut value: c_uint = 0;
4494 if oflags & O_CREAT != 0 {
4495 mode = args.next_arg::<mode_t>() & 0o666;
4496 value = args.next_arg::<c_uint>();
4497 if value > SEM_VALUE_MAX as c_uint {
4498 ERRNO = EINVAL;
4499 semtab_lock();
4500 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4501 semtab_unlock();
4502 return core::ptr::null_mut();
4503 }
4504 }
4505
4506 if oflags != O_CREAT | O_EXCL {
4508 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4509 if fd >= 0 {
4510 let map = sys_mmap(
4511 core::ptr::null_mut(),
4512 core::mem::size_of::<sem_t>(),
4513 PROT_READ | PROT_WRITE,
4514 MAP_SHARED,
4515 fd as i32,
4516 0,
4517 );
4518 sys_close(fd);
4519 if map != MMAP_FAILED {
4520 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4521 return sem_register(map as *mut sem_t, st_ino, slot);
4522 }
4523 }
4524 if oflags == 0 {
4525 semtab_lock();
4527 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4528 semtab_unlock();
4529 return core::ptr::null_mut();
4530 }
4531 }
4532
4533 let mut tmp = [0u8; 32];
4535 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4536 tmp[..tmpname.len()].copy_from_slice(tmpname);
4537 let mut ts: timespec = core::mem::zeroed();
4539 sys_clock_gettime(0, &mut ts);
4540 let mut n = ts.tv_nsec;
4542 let mut pos = tmpname.len() - 1;
4543 tmp[pos] = 0;
4544 pos -= 1;
4545 loop {
4546 tmp[pos] = b'0' + (n % 10) as u8;
4547 n /= 10;
4548 if n == 0 || pos == 0 { break; }
4549 pos -= 1;
4550 }
4551 let tmp_path = tmp.as_ptr();
4553
4554 let mut newsem: sem_t = core::mem::zeroed();
4555 newsem.__val[0] = value as c_int;
4556 newsem.__val[1] = 0;
4557 newsem.__val[2] = 128; loop {
4560 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4561 if fd < 0 {
4562 if (-fd) as c_int == EEXIST { continue; }
4563 semtab_lock();
4564 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4565 semtab_unlock();
4566 return core::ptr::null_mut();
4567 }
4568 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4569 if written != core::mem::size_of::<sem_t>() as i64 {
4570 sys_close(fd);
4571 sys_unlink(tmp_path);
4572 semtab_lock();
4573 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4574 semtab_unlock();
4575 return core::ptr::null_mut();
4576 }
4577 let map = sys_mmap(
4578 core::ptr::null_mut(),
4579 core::mem::size_of::<sem_t>(),
4580 PROT_READ | PROT_WRITE,
4581 MAP_SHARED,
4582 fd as i32,
4583 0,
4584 );
4585 sys_close(fd);
4586 if map == MMAP_FAILED {
4587 sys_unlink(tmp_path);
4588 semtab_lock();
4589 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4590 semtab_unlock();
4591 return core::ptr::null_mut();
4592 }
4593 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4595 let e = if r < 0 { (-r) as c_int } else { 0 };
4596 sys_unlink(tmp_path);
4597 if e == 0 {
4598 let st_ino = get_ino(-1, buf.as_ptr());
4599 return sem_register(map as *mut sem_t, st_ino, slot);
4600 }
4601 sys_munmap(map, core::mem::size_of::<sem_t>());
4602 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4603 ERRNO = e;
4604 semtab_lock();
4605 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4606 semtab_unlock();
4607 return core::ptr::null_mut();
4608 }
4609 break;
4611 }
4612
4613 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4615 if fd < 0 {
4616 semtab_lock();
4617 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4618 semtab_unlock();
4619 return core::ptr::null_mut();
4620 }
4621 let map = sys_mmap(
4622 core::ptr::null_mut(),
4623 core::mem::size_of::<sem_t>(),
4624 PROT_READ | PROT_WRITE,
4625 MAP_SHARED,
4626 fd as i32,
4627 0,
4628 );
4629 sys_close(fd);
4630 if map == MMAP_FAILED {
4631 semtab_lock();
4632 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4633 semtab_unlock();
4634 return core::ptr::null_mut();
4635 }
4636 let st_ino = get_ino(-1, buf.as_ptr());
4637 sem_register(map as *mut sem_t, st_ino, slot)
4638}
4639
4640unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4641 let mut st: Stat = core::mem::zeroed();
4642 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4643 st.st_ino
4644 } else {
4645 0
4646 }
4647}
4648
4649unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4650 semtab_lock();
4651 for i in 0..SEMTAB_LEN {
4653 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4654 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
4656 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
4657 SEMTAB[i].refcnt += 1;
4658 let ret = SEMTAB[i].sem;
4659 semtab_unlock();
4660 return ret;
4661 }
4662 }
4663 SEMTAB[slot_hint as usize].sem = map;
4665 SEMTAB[slot_hint as usize].ino = ino;
4666 SEMTAB[slot_hint as usize].refcnt = 1;
4667 semtab_unlock();
4668 map
4669}
4670
4671const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
4672
4673#[no_mangle]
4674pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
4675 semtab_lock();
4676 for i in 0..SEMTAB_LEN {
4677 if SEMTAB[i].sem == sem {
4678 SEMTAB[i].refcnt -= 1;
4679 if SEMTAB[i].refcnt == 0 {
4680 SEMTAB[i].sem = core::ptr::null_mut();
4681 SEMTAB[i].ino = 0;
4682 semtab_unlock();
4683 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
4684 return 0;
4685 }
4686 semtab_unlock();
4687 return 0;
4688 }
4689 }
4690 semtab_unlock();
4691 0
4692}
4693
4694#[no_mangle]
4695pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
4696 shm_unlink(name)
4697}
4698
4699#[no_mangle]
4701pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
4702 if a_load(control) == 2 { return 0; }
4703 loop {
4704 match a_cas(control, 0, 1) {
4705 0 => {
4706 if let Some(f) = init_routine { f(); }
4707 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
4708 return 0;
4709 }
4710 1 => { a_cas(control, 1, 3); }
4711 3 => { futex_wait(control, 3); }
4712 _ => { return 0; }
4713 }
4714 }
4715}
4716
4717#[no_mangle]
4719pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
4720 let start = NEXT_KEY.load(Ordering::Relaxed);
4721 let mut j = start;
4722 loop {
4723 if KEY_DTORS[j].is_none() {
4724 KEY_DTORS[j] = dtor;
4725 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
4726 *key = j as pthread_key_t;
4727 return 0;
4728 }
4729 j = (j + 1) % PTHREAD_KEYS_MAX;
4730 if j == start { return EAGAIN; }
4731 }
4732}
4733#[no_mangle]
4734pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
4735 KEY_DTORS[key as usize] = None;
4736 for i in 0..MAX_THREADS {
4737 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
4738 }
4739 0
4740}
4741#[no_mangle]
4742pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
4743 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
4744}
4745#[no_mangle]
4746pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
4747 if let Some(slot) = find_thread() {
4748 slot.tsd[key as usize] = value as *mut c_void;
4749 0
4750 } else { EINVAL }
4751}
4752
4753unsafe fn run_cleanup_handlers(slot: &mut Thread) {
4755 let mut cb = slot.cancelbuf;
4756 while !cb.is_null() {
4757 let cur = &*cb;
4758 let f = cur.__f;
4759 let x = cur.__x;
4760 cb = cur.__next;
4761 if let Some(func) = f {
4762 func(x);
4763 }
4764 }
4765 slot.cancelbuf = core::ptr::null_mut();
4766}
4767
4768unsafe fn do_cancel() -> ! {
4769 if let Some(slot) = find_thread() {
4770 run_cleanup_handlers(slot);
4771 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
4773 futex_wake(&raw mut slot.detach_state, 1);
4774 }
4775 sys_exit_thread(0);
4776}
4777
4778extern "C" fn cancel_handler(_sig: c_int) {
4779 unsafe {
4780 if let Some(slot) = find_thread() {
4781 if slot.cancel != 0
4785 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
4786 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
4787 {
4788 do_cancel();
4789 }
4790 }
4791 }
4792}
4793
4794static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
4795
4796unsafe fn ensure_cancel_handler() {
4797 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
4798 let act = sigaction {
4799 sa_handler: cancel_handler as *const () as usize,
4800 sa_flags: SA_RESTORER,
4801 sa_restorer: sig_restorer as *const () as usize,
4802 sa_mask: [!0u64],
4803 };
4804 sys_rt_sigaction(SIGCANCEL, &act as *const sigaction, core::ptr::null_mut(), 8);
4805 }
4806}
4807
4808#[no_mangle]
4809pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
4810 let slot = thread as *mut Thread;
4811 if slot.is_null() { return EINVAL; }
4812 ensure_cancel_handler();
4813 a_store(&raw mut (*slot).cancel, 1);
4814 let tid = (*slot).tid;
4815 if tid > 0 {
4816 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
4817 }
4818 0
4819}
4820#[no_mangle]
4821pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
4822 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
4823 if let Some(slot) = find_thread() {
4824 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
4825 slot.cancel_state = state;
4826 0
4827 } else { EINVAL }
4828}
4829#[no_mangle]
4830pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
4831 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
4832 if let Some(slot) = find_thread() {
4833 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
4834 slot.cancel_type = type_;
4835 0
4836 } else { EINVAL }
4837}
4838#[no_mangle]
4839pub unsafe extern "C" fn pthread_testcancel() {
4840 if let Some(slot) = find_thread() {
4841 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
4842 do_cancel();
4843 }
4844 }
4845}
4846
4847#[no_mangle]
4848pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
4849 (*cb).__f = f;
4850 (*cb).__x = x;
4851 if let Some(slot) = find_thread() {
4852 (*cb).__next = slot.cancelbuf;
4853 slot.cancelbuf = cb;
4854 } else {
4855 (*cb).__next = core::ptr::null_mut();
4856 }
4857}
4858
4859#[no_mangle]
4860pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
4861 if let Some(slot) = find_thread() {
4862 slot.cancelbuf = (*cb).__next;
4863 }
4864 if run != 0 {
4865 if let Some(f) = (*cb).__f {
4866 f((*cb).__x);
4867 }
4868 }
4869}
4870
4871#[no_mangle]
4872pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
4873 let slot = thread as *mut Thread;
4874 if slot.is_null() { return EINVAL; }
4875 let tid = (*slot).tid;
4876 if tid <= 0 { return EINVAL; }
4877 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
4878}
4879
4880#[no_mangle]
4881pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
4882 sigprocmask(how, set, oldset)
4883}
4884
4885
4886#[repr(C)]
4887pub struct lconv {
4888 pub decimal_point: *mut c_char,
4889 pub thousands_sep: *mut c_char,
4890 pub grouping: *mut c_char,
4891 pub int_curr_symbol: *mut c_char,
4892 pub currency_symbol: *mut c_char,
4893 pub mon_decimal_point: *mut c_char,
4894 pub mon_thousands_sep: *mut c_char,
4895 pub mon_grouping: *mut c_char,
4896 pub positive_sign: *mut c_char,
4897 pub negative_sign: *mut c_char,
4898 pub int_frac_digits: c_char,
4899 pub frac_digits: c_char,
4900 pub p_cs_precedes: c_char,
4901 pub p_sep_by_space: c_char,
4902 pub n_cs_precedes: c_char,
4903 pub n_sep_by_space: c_char,
4904 pub p_sign_posn: c_char,
4905 pub n_sign_posn: c_char,
4906 pub int_p_cs_precedes: c_char,
4907 pub int_p_sep_by_space: c_char,
4908 pub int_n_cs_precedes: c_char,
4909 pub int_n_sep_by_space: c_char,
4910 pub int_p_sign_posn: c_char,
4911 pub int_n_sign_posn: c_char,
4912}
4913
4914static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
4915static C_NAME: [u8; 2] = [b'C', 0];
4916static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
4917static mut LOCALE_CTYPE_UTF8: bool = true;
4918static mut EMPTY_STR: [c_char; 1] = [0];
4919static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
4920static mut LCONV: lconv = lconv {
4921 decimal_point: core::ptr::null_mut(),
4922 thousands_sep: core::ptr::null_mut(),
4923 grouping: core::ptr::null_mut(),
4924 int_curr_symbol: core::ptr::null_mut(),
4925 currency_symbol: core::ptr::null_mut(),
4926 mon_decimal_point: core::ptr::null_mut(),
4927 mon_thousands_sep: core::ptr::null_mut(),
4928 mon_grouping: core::ptr::null_mut(),
4929 positive_sign: core::ptr::null_mut(),
4930 negative_sign: core::ptr::null_mut(),
4931 int_frac_digits: (-1i32) as c_char,
4932 frac_digits: (-1i32) as c_char,
4933 p_cs_precedes: (-1i32) as c_char,
4934 p_sep_by_space: (-1i32) as c_char,
4935 n_cs_precedes: (-1i32) as c_char,
4936 n_sep_by_space: (-1i32) as c_char,
4937 p_sign_posn: (-1i32) as c_char,
4938 n_sign_posn: (-1i32) as c_char,
4939 int_p_cs_precedes: (-1i32) as c_char,
4940 int_p_sep_by_space: (-1i32) as c_char,
4941 int_n_cs_precedes: (-1i32) as c_char,
4942 int_n_sep_by_space: (-1i32) as c_char,
4943 int_p_sign_posn: (-1i32) as c_char,
4944 int_n_sign_posn: (-1i32) as c_char,
4945};
4946
4947unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
4948 let len = strlen(s as *const c_char) as usize;
4949 let s_slice = core::slice::from_raw_parts(s, len);
4950 if needle.len() > len { return false; }
4951 for i in 0..=len - needle.len() {
4952 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
4953 return true;
4954 }
4955 }
4956 false
4957}
4958
4959#[no_mangle]
4960pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
4961 if locale.is_null() || *locale == 0 {
4962 return LOCALE_NAME as *mut c_char;
4963 }
4964 let name = locale as *const u8;
4965 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
4966 LOCALE_CTYPE_UTF8 = false;
4967 return LOCALE_NAME as *mut c_char;
4968 }
4969 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
4970 LOCALE_CTYPE_UTF8 = true;
4971 return LOCALE_NAME as *mut c_char;
4972 }
4973 core::ptr::null_mut()
4974}
4975
4976#[no_mangle]
4977pub unsafe extern "C" fn localeconv() -> *mut lconv {
4978 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
4979 let lconv = core::ptr::addr_of_mut!(LCONV);
4980 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
4981 (*lconv).thousands_sep = empty;
4982 (*lconv).grouping = empty;
4983 (*lconv).int_curr_symbol = empty;
4984 (*lconv).currency_symbol = empty;
4985 (*lconv).mon_decimal_point = empty;
4986 (*lconv).mon_thousands_sep = empty;
4987 (*lconv).mon_grouping = empty;
4988 (*lconv).positive_sign = empty;
4989 (*lconv).negative_sign = empty;
4990 lconv
4991}
4992
4993pub type locale_t = *mut c_void;
4994static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
4995
4996static mut C_LOCALE_STORAGE: c_int = 0;
4997const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
4998const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
4999
5000#[no_mangle]
5001pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5002 if !name.is_null() && *name != 0 {
5003 let n = name as *const u8;
5004 if strcmp(n, b"C\0".as_ptr()) != 0
5005 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5006 {
5007 return core::ptr::null_mut();
5008 }
5009 }
5010 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5011 C_LOCALE
5012 } else {
5013 core::ptr::null_mut()
5014 }
5015}
5016
5017#[no_mangle]
5018pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5019
5020#[no_mangle]
5021pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5022 let old = CURRENT_LOCALE;
5023 if !loc.is_null() {
5024 CURRENT_LOCALE = loc;
5025 }
5026 old
5027}
5028
5029#[no_mangle]
5030pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5031 if loc.is_null() {
5032 return core::ptr::null_mut();
5033 }
5034 C_LOCALE
5035}
5036
5037const NL_ITEM_CODESET: c_int = 14;
5038const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5039const NL_ITEM_THOUSEP: c_int = 0x10001;
5040const NL_ITEM_YESEXPR: c_int = 0x50000;
5041const NL_ITEM_NOEXPR: c_int = 0x50001;
5042
5043const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5044Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5045Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5046January\0February\0March\0April\0May\0June\0July\0August\0\
5047September\0October\0November\0December\0\
5048AM\0PM\0\
5049%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5050\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5051
5052const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5053const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5054
5055unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5056 let mut p = table;
5057 while idx > 0 {
5058 while *p != 0 { p = p.add(1); }
5059 p = p.add(1);
5060 idx -= 1;
5061 }
5062 p as *mut c_char
5063}
5064
5065#[no_mangle]
5066pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5067 if item == NL_ITEM_CODESET {
5068 return if LOCALE_CTYPE_UTF8 {
5069 b"UTF-8\0".as_ptr() as *mut c_char
5070 } else {
5071 b"US-ASCII\0".as_ptr() as *mut c_char
5072 };
5073 }
5074 let cat = item >> 16;
5075 let idx = item & 0xFFFF;
5076 match cat {
5077 1 => {
5078 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5079 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5080 }
5081 2 => {
5082 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5083 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5084 }
5085 5 => {
5086 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5087 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5088 }
5089 _ => b"\0".as_ptr() as *mut c_char,
5090 }
5091}
5092
5093pub type nl_catd = *mut c_void;
5094
5095#[no_mangle]
5096pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5097 !0usize as nl_catd
5098}
5099
5100#[no_mangle]
5101pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5102
5103#[no_mangle]
5104pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5105 if catd == !0usize as nl_catd { return s as *mut c_char; }
5106 s as *mut c_char
5107}
5108
5109pub type IconvT = *mut c_void;
5110
5111const ENC_UTF8: i32 = 1;
5112const ENC_UTF16LE: i32 = 2;
5113const ENC_UTF16BE: i32 = 3;
5114const ENC_UTF32LE: i32 = 4;
5115const ENC_UTF32BE: i32 = 5;
5116const ENC_WCHAR_T: i32 = 6;
5117const ENC_ASCII: i32 = 7;
5118const ENC_LATIN1: i32 = 8;
5119const ENC_WIN1252: i32 = 9;
5120const ENC_WIN1251: i32 = 10;
5121const ENC_KOI8R: i32 = 11;
5122const ENC_GBK: i32 = 12;
5123const ENC_GB2312: i32 = 13;
5124const ENC_BIG5: i32 = 14;
5125const ENC_EUCJP: i32 = 15;
5126const ENC_SHIFTJIS: i32 = 16;
5127const ENC_ISO8859_2: i32 = 17;
5128const ENC_ISO8859_3: i32 = 18;
5129const ENC_ISO8859_4: i32 = 19;
5130const ENC_ISO8859_5: i32 = 20;
5131const ENC_ISO8859_6: i32 = 21;
5132const ENC_ISO8859_7: i32 = 22;
5133const ENC_ISO8859_8: i32 = 23;
5134const ENC_ISO8859_9: i32 = 24;
5135const ENC_ISO8859_10: i32 = 25;
5136const ENC_ISO8859_11: i32 = 26;
5137const ENC_ISO8859_13: i32 = 27;
5138const ENC_ISO8859_14: i32 = 28;
5139const ENC_ISO8859_15: i32 = 29;
5140const ENC_ISO8859_16: i32 = 30;
5141
5142include!("iconv_iso8859.rs");
5143
5144fn make_cd(from: i32, to: i32) -> IconvT {
5145 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5146}
5147fn extract_from(cd: IconvT) -> i32 {
5148 ((cd as usize) >> 16) as i32
5149}
5150fn extract_to(cd: IconvT) -> i32 {
5151 (((cd as usize) >> 1) & 0x7fff) as i32
5152}
5153
5154unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5155 let mut i = input;
5156 let mut j = 0;
5157 while *i != 0 && j < target.len() {
5158 let mut c = *i;
5159 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5160 c = c.to_ascii_lowercase();
5161 if c != target[j] { return false; }
5162 i = i.add(1);
5163 j += 1;
5164 }
5165 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5166 *i == 0 && j == target.len()
5167}
5168
5169unsafe fn find_encoding(name: *const u8) -> i32 {
5170 if name.is_null() { return -1; }
5171 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5172 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5173 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5174 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5175 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5176 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5177 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5178 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5179 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5180 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5181 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5182 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5183 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5184 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5185 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5186 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5187 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5188 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5189 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5190 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5191 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5192 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5193 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5194 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5195 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5196 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5197 if match_name(name, b"gb2312") { return ENC_GB2312; }
5198 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5199 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5200 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5201 -1
5202}
5203
5204fn uni_to_jis(c: u32) -> u16 {
5205 let mut b = 0usize;
5206 let mut nel = REV_JIS.len();
5207 loop {
5208 let i = nel / 2;
5209 let j = REV_JIS[b + i] as usize;
5210 let row = j / 256;
5211 let col = j % 256;
5212 let d = JIS0208[row * 94 + col] as u32;
5213 if d == c { return (j as u16) + 0x2121; }
5214 if nel == 1 { return 0; }
5215 if c < d { nel /= 2; }
5216 else { b += i; nel -= nel / 2; }
5217 }
5218}
5219
5220unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5221 if src_left == 0 { return (0, 0, EINVAL); }
5222 match enc {
5223 ENC_UTF8 => {
5224 let c = *src;
5225 if c < 128 { return (c as u32, 1, 0); }
5226 if c < 0xC2 { return (0, 0, EILSEQ); }
5227 if c < 0xE0 {
5228 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5229 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5230 }
5231 if c < 0xF0 {
5232 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5233 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5234 if cp < 0x800 { return (0, 0, EILSEQ); }
5235 return (cp, 3, 0);
5236 }
5237 if c < 0xF8 {
5238 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5239 let cp = ((c as u32 & 0x07) << 18) | ((*src.add(1) as u32 & 0x3F) << 12) | ((*src.add(2) as u32 & 0x3F) << 6) | (*src.add(3) as u32 & 0x3F);
5240 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5241 return (cp, 4, 0);
5242 }
5243 (0, 0, EILSEQ)
5244 }
5245 ENC_UTF16LE => {
5246 if src_left < 2 { return (0, 0, EINVAL); }
5247 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5248 if c >= 0xD800 && c <= 0xDBFF {
5249 if src_left < 4 { return (0, 0, EINVAL); }
5250 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5251 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5252 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5253 }
5254 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5255 (c, 2, 0)
5256 }
5257 ENC_UTF16BE => {
5258 if src_left < 2 { return (0, 0, EINVAL); }
5259 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5260 if c >= 0xD800 && c <= 0xDBFF {
5261 if src_left < 4 { return (0, 0, EINVAL); }
5262 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5263 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5264 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5265 }
5266 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5267 (c, 2, 0)
5268 }
5269 ENC_UTF32LE => {
5270 if src_left < 4 { return (0, 0, EINVAL); }
5271 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5272 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5273 if c >= 0x110000 { return (0, 0, EILSEQ); }
5274 (c, 4, 0)
5275 }
5276 ENC_UTF32BE => {
5277 if src_left < 4 { return (0, 0, EINVAL); }
5278 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5279 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5280 if c >= 0x110000 { return (0, 0, EILSEQ); }
5281 (c, 4, 0)
5282 }
5283 ENC_WCHAR_T => {
5284 if src_left < 4 { return (0, 0, EINVAL); }
5285 let c = *(src as *const u32);
5286 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5287 if c >= 0x110000 { return (0, 0, EILSEQ); }
5288 (c, 4, 0)
5289 }
5290 ENC_ASCII => {
5291 let c = *src as u32;
5292 if c >= 128 { return (0, 0, EILSEQ); }
5293 (c, 1, 0)
5294 }
5295 ENC_LATIN1 => (*src as u32, 1, 0),
5296 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5297 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5298 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5299 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5300 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5301 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5302 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5303 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5304 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5305 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5306 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5307 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5308 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5309 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5310 ENC_WIN1252 => {
5311 let b = *src;
5312 if b < 128 { return (b as u32, 1, 0); }
5313 (WIN1252_TO_U[b as usize - 128], 1, 0)
5314 }
5315 ENC_WIN1251 => {
5316 let b = *src;
5317 if b < 128 { return (b as u32, 1, 0); }
5318 (WIN1251_TO_U[b as usize - 128], 1, 0)
5319 }
5320 ENC_KOI8R => {
5321 let b = *src;
5322 if b < 128 { return (b as u32, 1, 0); }
5323 (KOI8R_TO_U[b as usize - 128], 1, 0)
5324 }
5325 ENC_GBK | ENC_GB2312 => {
5326 let c = *src;
5327 if c < 128 { return (c as u32, 1, 0); }
5328 if c == 128 { return (0x20AC, 1, 0); }
5329 if src_left < 2 { return (0, 0, EINVAL); }
5330 let d = *src.add(1);
5331 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5332 let row = (c as usize).wrapping_sub(0x81);
5333 if row >= 126 { return (0, 0, EILSEQ); }
5334 let mut col = (d as usize) - 0x40;
5335 if col > 63 { col -= 1; }
5336 let cp = GB18030_TABLE[row * 190 + col] as u32;
5337 if cp == 0 { return (0, 0, EILSEQ); }
5338 (cp, 2, 0)
5339 }
5340 ENC_BIG5 => {
5341 let c = *src;
5342 if c < 128 { return (c as u32, 1, 0); }
5343 if src_left < 2 { return (0, 0, EINVAL); }
5344 let d = *src.add(1);
5345 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5346 let mut col = (d as usize) - 0x40;
5347 if col > 0x3E { col -= 0x22; }
5348 if c >= 0xA1 && c < 0xFA {
5349 let row = (c as usize) - 0xA1;
5350 if row >= 89 { return (0, 0, EILSEQ); }
5351 let cp = BIG5_TABLE[row * 157 + col] as u32;
5352 if cp == 0 { return (0, 0, EILSEQ); }
5353 return (cp, 2, 0);
5354 }
5355 (0, 0, EILSEQ)
5356 }
5357 ENC_EUCJP => {
5358 let c = *src;
5359 if c < 128 { return (c as u32, 1, 0); }
5360 if c == 0x8E {
5361 if src_left < 2 { return (0, 0, EINVAL); }
5362 let d = *src.add(1);
5363 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5364 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5365 }
5366 if c < 0xA1 { return (0, 0, EILSEQ); }
5367 if src_left < 2 { return (0, 0, EINVAL); }
5368 let d = *src.add(1);
5369 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5370 let row = (c as usize) - 0xA1;
5371 let col = (d as usize) - 0xA1;
5372 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5373 let cp = JIS0208[row * 94 + col] as u32;
5374 if cp == 0 { return (0, 0, EILSEQ); }
5375 (cp, 2, 0)
5376 }
5377 ENC_SHIFTJIS => {
5378 let c = *src;
5379 if c < 128 { return (c as u32, 1, 0); }
5380 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5381 if src_left < 2 { return (0, 0, EINVAL); }
5382 let d = *src.add(1);
5383 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5384 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5385 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5386 else { return (0, 0, EILSEQ); };
5387 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5388 let mut dd = d as usize;
5389 if dd > 127 { dd -= 1; }
5390 (dd - 64, row * 2)
5391 } else if d >= 159 && d <= 252 {
5392 ((d as usize) - 159, row * 2 + 1)
5393 } else {
5394 return (0, 0, EILSEQ);
5395 };
5396 if row_adj >= 84 { return (0, 0, EILSEQ); }
5397 let cp = JIS0208[row_adj * 94 + col] as u32;
5398 if cp == 0 { return (0, 0, EILSEQ); }
5399 (cp, 2, 0)
5400 }
5401 _ => (0, 0, EILSEQ),
5402 }
5403}
5404
5405unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5406 match enc {
5407 ENC_UTF8 => {
5408 if c < 0x80 {
5409 if dst_left < 1 { return (0, E2BIG); }
5410 *dst = c as u8; return (1, 0);
5411 }
5412 if c < 0x800 {
5413 if dst_left < 2 { return (0, E2BIG); }
5414 *dst = (0xC0 | (c >> 6)) as u8;
5415 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5416 return (2, 0);
5417 }
5418 if c < 0x10000 {
5419 if dst_left < 3 { return (0, E2BIG); }
5420 *dst = (0xE0 | (c >> 12)) as u8;
5421 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5422 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5423 return (3, 0);
5424 }
5425 if dst_left < 4 { return (0, E2BIG); }
5426 *dst = (0xF0 | (c >> 18)) as u8;
5427 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5428 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5429 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5430 (4, 0)
5431 }
5432 ENC_UTF16LE => {
5433 if c < 0x10000 {
5434 if dst_left < 2 { return (0, E2BIG); }
5435 *dst = (c & 0xFF) as u8;
5436 *dst.add(1) = (c >> 8) as u8;
5437 return (2, 0);
5438 }
5439 if dst_left < 4 { return (0, E2BIG); }
5440 let c = c - 0x10000;
5441 let hi = ((c >> 10) + 0xD800) as u16;
5442 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5443 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5444 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5445 (4, 0)
5446 }
5447 ENC_UTF16BE => {
5448 if c < 0x10000 {
5449 if dst_left < 2 { return (0, E2BIG); }
5450 *dst = (c >> 8) as u8;
5451 *dst.add(1) = (c & 0xFF) as u8;
5452 return (2, 0);
5453 }
5454 if dst_left < 4 { return (0, E2BIG); }
5455 let c = c - 0x10000;
5456 let hi = ((c >> 10) + 0xD800) as u16;
5457 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5458 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5459 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5460 (4, 0)
5461 }
5462 ENC_UTF32LE => {
5463 if dst_left < 4 { return (0, E2BIG); }
5464 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5465 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5466 (4, 0)
5467 }
5468 ENC_UTF32BE => {
5469 if dst_left < 4 { return (0, E2BIG); }
5470 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5471 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5472 (4, 0)
5473 }
5474 ENC_WCHAR_T => {
5475 if dst_left < 4 { return (0, E2BIG); }
5476 *(dst as *mut u32) = c;
5477 (4, 0)
5478 }
5479 ENC_ASCII => {
5480 if c < 128 {
5481 if dst_left < 1 { return (0, E2BIG); }
5482 *dst = c as u8; return (1, 0);
5483 }
5484 (0, EILSEQ)
5485 }
5486 ENC_LATIN1 => {
5487 if c < 256 {
5488 if dst_left < 1 { return (0, E2BIG); }
5489 *dst = c as u8; return (1, 0);
5490 }
5491 (0, EILSEQ)
5492 }
5493 ENC_ISO8859_2 => {
5494 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5495 if dst_left < 1 { return (0, E2BIG); }
5496 *dst = b; return (1, 0);
5497 }
5498 (0, EILSEQ)
5499 }
5500 ENC_ISO8859_3 => {
5501 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5502 if dst_left < 1 { return (0, E2BIG); }
5503 *dst = b; return (1, 0);
5504 }
5505 (0, EILSEQ)
5506 }
5507 ENC_ISO8859_4 => {
5508 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5509 if dst_left < 1 { return (0, E2BIG); }
5510 *dst = b; return (1, 0);
5511 }
5512 (0, EILSEQ)
5513 }
5514 ENC_ISO8859_5 => {
5515 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5516 if dst_left < 1 { return (0, E2BIG); }
5517 *dst = b; return (1, 0);
5518 }
5519 (0, EILSEQ)
5520 }
5521 ENC_ISO8859_6 => {
5522 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5523 if dst_left < 1 { return (0, E2BIG); }
5524 *dst = b; return (1, 0);
5525 }
5526 (0, EILSEQ)
5527 }
5528 ENC_ISO8859_7 => {
5529 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5530 if dst_left < 1 { return (0, E2BIG); }
5531 *dst = b; return (1, 0);
5532 }
5533 (0, EILSEQ)
5534 }
5535 ENC_ISO8859_8 => {
5536 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5537 if dst_left < 1 { return (0, E2BIG); }
5538 *dst = b; return (1, 0);
5539 }
5540 (0, EILSEQ)
5541 }
5542 ENC_ISO8859_9 => {
5543 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5544 if dst_left < 1 { return (0, E2BIG); }
5545 *dst = b; return (1, 0);
5546 }
5547 (0, EILSEQ)
5548 }
5549 ENC_ISO8859_10 => {
5550 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5551 if dst_left < 1 { return (0, E2BIG); }
5552 *dst = b; return (1, 0);
5553 }
5554 (0, EILSEQ)
5555 }
5556 ENC_ISO8859_11 => {
5557 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5558 if dst_left < 1 { return (0, E2BIG); }
5559 *dst = b; return (1, 0);
5560 }
5561 (0, EILSEQ)
5562 }
5563 ENC_ISO8859_13 => {
5564 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5565 if dst_left < 1 { return (0, E2BIG); }
5566 *dst = b; return (1, 0);
5567 }
5568 (0, EILSEQ)
5569 }
5570 ENC_ISO8859_14 => {
5571 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5572 if dst_left < 1 { return (0, E2BIG); }
5573 *dst = b; return (1, 0);
5574 }
5575 (0, EILSEQ)
5576 }
5577 ENC_ISO8859_15 => {
5578 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5579 if dst_left < 1 { return (0, E2BIG); }
5580 *dst = b; return (1, 0);
5581 }
5582 (0, EILSEQ)
5583 }
5584 ENC_ISO8859_16 => {
5585 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5586 if dst_left < 1 { return (0, E2BIG); }
5587 *dst = b; return (1, 0);
5588 }
5589 (0, EILSEQ)
5590 }
5591 ENC_WIN1252 => {
5592 if c < 128 {
5593 if dst_left < 1 { return (0, E2BIG); }
5594 *dst = c as u8; return (1, 0);
5595 }
5596 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5597 if dst_left < 1 { return (0, E2BIG); }
5598 *dst = c as u8; return (1, 0);
5599 }
5600 for i in 0..128usize {
5601 if WIN1252_TO_U[i] == c {
5602 if dst_left < 1 { return (0, E2BIG); }
5603 *dst = (i + 128) as u8; return (1, 0);
5604 }
5605 }
5606 (0, EILSEQ)
5607 }
5608 ENC_WIN1251 => {
5609 if c < 128 {
5610 if dst_left < 1 { return (0, E2BIG); }
5611 *dst = c as u8; return (1, 0);
5612 }
5613 for i in 0..128usize {
5614 if WIN1251_TO_U[i] == c {
5615 if dst_left < 1 { return (0, E2BIG); }
5616 *dst = (i + 128) as u8; return (1, 0);
5617 }
5618 }
5619 (0, EILSEQ)
5620 }
5621 ENC_KOI8R => {
5622 if c < 128 {
5623 if dst_left < 1 { return (0, E2BIG); }
5624 *dst = c as u8; return (1, 0);
5625 }
5626 for i in 0..128usize {
5627 if KOI8R_TO_U[i] == c {
5628 if dst_left < 1 { return (0, E2BIG); }
5629 *dst = (i + 128) as u8; return (1, 0);
5630 }
5631 }
5632 (0, EILSEQ)
5633 }
5634 ENC_GBK | ENC_GB2312 => {
5635 if c < 128 {
5636 if dst_left < 1 { return (0, E2BIG); }
5637 *dst = c as u8; return (1, 0);
5638 }
5639 if c == 0x20AC {
5640 if dst_left < 1 { return (0, E2BIG); }
5641 *dst = 128; return (1, 0);
5642 }
5643 for row in 0..126usize {
5644 for col in 0..190usize {
5645 if GB18030_TABLE[row * 190 + col] as u32 == c {
5646 if dst_left < 2 { return (0, E2BIG); }
5647 *dst = (row + 0x81) as u8;
5648 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5649 return (2, 0);
5650 }
5651 }
5652 }
5653 (0, EILSEQ)
5654 }
5655 ENC_BIG5 => {
5656 if c < 128 {
5657 if dst_left < 1 { return (0, E2BIG); }
5658 *dst = c as u8; return (1, 0);
5659 }
5660 for row in 0..89usize {
5661 for col in 0..157usize {
5662 if BIG5_TABLE[row * 157 + col] as u32 == c {
5663 if dst_left < 2 { return (0, E2BIG); }
5664 *dst = (row + 0xA1) as u8;
5665 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
5666 return (2, 0);
5667 }
5668 }
5669 }
5670 (0, EILSEQ)
5671 }
5672 ENC_EUCJP => {
5673 if c < 128 {
5674 if dst_left < 1 { return (0, E2BIG); }
5675 *dst = c as u8; return (1, 0);
5676 }
5677 if c >= 0xFF61 && c <= 0xFF9F {
5678 if dst_left < 2 { return (0, E2BIG); }
5679 *dst = 0x8E;
5680 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
5681 return (2, 0);
5682 }
5683 let jis = uni_to_jis(c);
5684 if jis == 0 { return (0, EILSEQ); }
5685 if dst_left < 2 { return (0, E2BIG); }
5686 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
5687 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
5688 (2, 0)
5689 }
5690 ENC_SHIFTJIS => {
5691 if c < 128 {
5692 if dst_left < 1 { return (0, E2BIG); }
5693 *dst = c as u8; return (1, 0);
5694 }
5695 if c >= 0xFF61 && c <= 0xFF9F {
5696 if dst_left < 1 { return (0, E2BIG); }
5697 *dst = (c - 0xFF61 + 0xA1) as u8;
5698 return (1, 0);
5699 }
5700 let jis = uni_to_jis(c);
5701 if jis == 0 { return (0, EILSEQ); }
5702 if dst_left < 2 { return (0, E2BIG); }
5703 let r = (jis >> 8) as usize;
5704 let d = (jis & 0xFF) as usize;
5705 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
5706 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
5707 (2, 0)
5708 }
5709 _ => (0, EILSEQ),
5710 }
5711}
5712
5713#[no_mangle]
5714pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
5715 let to = find_encoding(tocode as *const u8);
5716 let from = find_encoding(fromcode as *const u8);
5717 if to < 0 || from < 0 {
5718 ERRNO = EINVAL;
5719 return !0usize as IconvT;
5720 }
5721 make_cd(from, to)
5722}
5723
5724#[no_mangle]
5725pub unsafe extern "C" fn iconv(
5726 cd: IconvT,
5727 inbuf: *mut *mut c_char,
5728 inbytesleft: *mut SizeT,
5729 outbuf: *mut *mut c_char,
5730 outbytesleft: *mut SizeT,
5731) -> SizeT {
5732 if cd == !0usize as IconvT {
5733 ERRNO = EINVAL;
5734 return !0usize;
5735 }
5736 if inbuf.is_null() || outbuf.is_null() { return 0; }
5737 let from = extract_from(cd);
5738 let to = extract_to(cd);
5739 let mut src = *inbuf as *const u8;
5740 let mut dst = *outbuf as *mut u8;
5741 let mut src_left = *inbytesleft;
5742 let mut dst_left = *outbytesleft;
5743 let mut subst = 0usize;
5744 while src_left > 0 {
5745 let (cp, consumed, err) = iconv_decode(from, src, src_left);
5746 if err != 0 {
5747 if err == EINVAL { break; }
5748 ERRNO = err;
5749 return !0usize;
5750 }
5751 let (written, err) = iconv_encode(to, cp, dst, dst_left);
5752 if err != 0 {
5753 if err == E2BIG {
5754 ERRNO = E2BIG;
5755 return !0usize;
5756 }
5757 if dst_left < 1 {
5758 ERRNO = E2BIG;
5759 return !0usize;
5760 }
5761 *dst = b'*';
5762 dst = dst.add(1);
5763 dst_left -= 1;
5764 subst += 1;
5765 } else {
5766 dst = dst.add(written);
5767 dst_left -= written;
5768 }
5769 src = src.add(consumed);
5770 src_left -= consumed;
5771 }
5772 *inbuf = src as *mut c_char;
5773 *outbuf = dst as *mut c_char;
5774 *inbytesleft = src_left;
5775 *outbytesleft = dst_left;
5776 subst
5777}
5778
5779#[no_mangle]
5780pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
5781
5782#[no_mangle]
5787pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
5788 sys_write(fd as i64, buf as *const u8, count) as SSizeT
5789}
5790
5791#[no_mangle]
5792pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
5793 sys_read(fd as i64, buf as *mut u8, count) as SSizeT
5794}
5795
5796#[no_mangle]
5797pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
5798 sys_open(path as *const u8, flags as i64, mode as i64) as c_int
5799}
5800
5801#[no_mangle]
5802pub unsafe extern "C" fn close(fd: c_int) -> c_int {
5803 sys_close(fd as i64);
5804 0
5805}
5806
5807#[no_mangle]
5808pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
5809 sys_lseek(fd as i64, offset, whence as i64)
5810}
5811
5812const O_RDONLY: i32 = 0;
5817const O_WRONLY: i32 = 1;
5818const O_RDWR: i32 = 2;
5819const O_CREAT: i32 = 64;
5820const O_TRUNC: i32 = 512;
5821const O_APPEND: i32 = 1024;
5822const O_EXCL: i32 = 128;
5823const O_NONBLOCK: i32 = 2048;
5824const O_NOFOLLOW: i32 = 0x40000;
5825const O_CLOEXEC: i32 = 0x80000;
5826
5827const F_GETFD: i32 = 1;
5828const F_SETFD: i32 = 2;
5829const F_GETFL: i32 = 3;
5830const F_SETFL: i32 = 4;
5831const F_GETLK: i32 = 5;
5832const F_SETLK: i32 = 6;
5833const F_SETLKW: i32 = 7;
5834const F_DUPFD: i32 = 0;
5835const F_DUPFD_CLOEXEC: i32 = 1030;
5836const FD_CLOEXEC: i32 = 1;
5837
5838const TIOCGWINSZ: u32 = 0x5413;
5839
5840#[repr(C)]
5841struct winsize {
5842 ws_row: u16,
5843 ws_col: u16,
5844 ws_xpixel: u16,
5845 ws_ypixel: u16,
5846}
5847
5848#[inline]
5849unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
5850 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
5851}
5852
5853#[inline]
5854unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
5855 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
5856}
5857
5858#[inline]
5859unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
5860 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
5861}
5862
5863#[inline]
5864unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
5865 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
5866}
5867
5868#[inline]
5869unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
5870 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
5871}
5872
5873#[inline]
5874unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
5875 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
5876}
5877
5878const UNGET: usize = 8;
5883const F_PERM: u32 = 1;
5884const F_NORD: u32 = 4;
5885const F_NOWR: u32 = 8;
5886const F_EOF: u32 = 16;
5887const F_ERR: u32 = 32;
5888const F_SVB: u32 = 64;
5889const F_APP: u32 = 128;
5890
5891const BUFSIZ: usize = 1024;
5892
5893const _IOFBF: c_int = 0;
5894const _IOLBF: c_int = 1;
5895const _IONBF: c_int = 2;
5896
5897const SEEK_SET: c_int = 0;
5898const SEEK_CUR: c_int = 1;
5899const SEEK_END: c_int = 2;
5900
5901#[repr(C)]
5903pub struct FILE {
5904 flags: c_uint,
5905 rpos: *mut u8,
5906 rend: *mut u8,
5907 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
5908 wend: *mut u8,
5909 wpos: *mut u8,
5910 mustbezero_1: *mut u8,
5911 wbase: *mut u8,
5912 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
5913 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
5914 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
5915 buf: *mut u8,
5916 buf_size: usize,
5917 prev: *mut FILE,
5918 next: *mut FILE,
5919 fd: c_int,
5920 pipe_pid: c_int,
5921 lockcount: c_long,
5922 mode: c_int,
5923 lock: c_int,
5924 lbf: c_int,
5925 cookie: *mut c_void,
5926 off: i64,
5927 getln_buf: *mut c_char,
5928 mustbezero_2: *mut c_void,
5929 shend: *mut u8,
5930 shlim: i64,
5931 shcnt: i64,
5932 ungotten: [c_int; UNGET],
5933 ungotten_count: c_int,
5934 _eof: c_int,
5935 _err: c_int,
5936}
5937
5938static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5939static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5940static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5941
5942static mut STDIN_FILE: FILE = FILE {
5943 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5944 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5945 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5946 read_fn: None, write_fn: None, seek_fn: None,
5947 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5948 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5949 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: -1, lbf: -1,
5950 cookie: core::ptr::null_mut(), off: 0,
5951 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5952 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5953 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5954};
5955static mut STDOUT_FILE: FILE = FILE {
5956 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5957 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5958 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5959 read_fn: None, write_fn: None, seek_fn: None,
5960 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5961 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5962 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: -1, lbf: -1,
5963 cookie: core::ptr::null_mut(), off: 0,
5964 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5965 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5966 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5967};
5968static mut STDERR_FILE: FILE = FILE {
5969 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5970 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5971 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5972 read_fn: None, write_fn: None, seek_fn: None,
5973 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5974 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5975 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: -1, lbf: -1,
5976 cookie: core::ptr::null_mut(), off: 0,
5977 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5978 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5979 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5980};
5981
5982#[no_mangle]
5983pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
5984#[no_mangle]
5985pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
5986#[no_mangle]
5987pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
5988
5989unsafe fn __stdio_init() {
5994 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
5995 STDIN_FILE.buf_size = BUFSIZ;
5996 STDIN_FILE.read_fn = Some(__stdio_read);
5997 STDIN_FILE.write_fn = Some(__stdio_write);
5998 STDIN_FILE.seek_fn = Some(__stdio_seek);
5999 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6000 STDOUT_FILE.buf_size = BUFSIZ;
6001 STDOUT_FILE.lbf = b'\n' as c_int;
6002 STDOUT_FILE.read_fn = Some(__stdio_read);
6003 STDOUT_FILE.write_fn = Some(__stdio_write);
6004 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6005 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6006 STDERR_FILE.buf_size = BUFSIZ;
6007 STDERR_FILE.read_fn = Some(__stdio_read);
6008 STDERR_FILE.write_fn = Some(__stdio_write);
6009 STDERR_FILE.seek_fn = Some(__stdio_seek);
6010}
6011
6012unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6013 (f as *mut u8).add(core::mem::size_of::<FILE>())
6014}
6015
6016unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6017 let n = sys_read((*f).fd as i64, buf, len);
6018 if n <= 0 {
6019 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6020 return 0;
6021 }
6022 n as usize
6023}
6024
6025unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6026 let l = (*f).wpos as usize - (*f).wbase as usize;
6027 let mut iov = [
6028 ((*f).wbase as *const u8, l),
6029 (buf, len),
6030 ];
6031 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6032 if (*f).flags & F_APP != 0 {
6033 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6034 }
6035 let mut rem = iov[0].1 + iov[1].1;
6036 let mut idx = 0usize;
6037 while rem > 0 {
6038 let ptr = iov[idx].0;
6039 let cnt = iov[idx].1;
6040 if cnt == 0 { idx += 1; continue; }
6041 let n = sys_write((*f).fd as i64, ptr, cnt);
6042 if n <= 0 {
6043 (*f).wpos = core::ptr::null_mut();
6044 (*f).wbase = core::ptr::null_mut();
6045 (*f).wend = core::ptr::null_mut();
6046 (*f).flags |= F_ERR;
6047 return if iov[idx].0 == buf { 0 } else { len };
6048 }
6049 rem -= n as usize;
6050 iov[idx].0 = iov[idx].0.add(n as usize);
6051 iov[idx].1 -= n as usize;
6052 if iov[idx].1 == 0 { idx += 1; }
6053 }
6054 (*f).wend = (*f).buf.add((*f).buf_size);
6055 (*f).wbase = (*f).buf;
6056 (*f).wpos = (*f).buf;
6057 len
6058}
6059
6060unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6061 sys_lseek((*f).fd as i64, off, whence as i64)
6062}
6063
6064unsafe fn init_file(
6065 f: *mut FILE,
6066 fd: c_int,
6067 mode: *const c_char,
6068 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6069 buf_area: *mut u8,
6070 buf_sz: usize,
6071) {
6072 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6073 (*f).fd = fd;
6074 (*f).close = close_fn;
6075 (*f).lock = -1;
6076 (*f).lbf = -1;
6077 (*f).buf = buf_area;
6078 (*f).buf_size = buf_sz;
6079 (*f).read_fn = Some(__stdio_read);
6080 (*f).write_fn = Some(__stdio_write);
6081 (*f).seek_fn = Some(__stdio_seek);
6082 let m = *mode;
6083 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6084 if m == b'r' as c_char && !has_plus {
6085 (*f).flags = F_NORD;
6086 } else if !has_plus {
6087 (*f).flags = F_NOWR;
6088 }
6089}
6090
6091unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6092 sys_close((*f).fd as i64);
6093 0
6094}
6095
6096unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6097 let mut flags: c_int;
6098 let m = *mode;
6099 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6100 flags = O_RDWR;
6101 } else if m == b'r' as c_char {
6102 flags = O_RDONLY;
6103 } else {
6104 flags = O_WRONLY;
6105 }
6106 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6107 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6108 if m != b'r' as c_char { flags |= O_CREAT; }
6109 if m == b'w' as c_char { flags |= O_TRUNC; }
6110 if m == b'a' as c_char { flags |= O_APPEND; }
6111 flags
6112}
6113
6114const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6115
6116unsafe fn flush_buf(f: *mut FILE) -> c_int {
6117 if (*f).wpos == (*f).wbase {
6118 if !(*f).wpos.is_null() {
6119 (*f).wend = (*f).buf.add((*f).buf_size);
6120 (*f).wpos = (*f).wbase;
6121 }
6122 return 0;
6123 }
6124 if let Some(wfunc) = (*f).write_fn {
6125 let ret = wfunc(f, core::ptr::null(), 0);
6126 if ret == 0 && (*f).wpos.is_null() { return -1; }
6127 return 0;
6128 }
6129 (*f).flags |= F_ERR;
6130 -1
6131}
6132
6133#[no_mangle]
6138pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6139 if filename.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6140 let m = *mode;
6141 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6142 ERRNO = EINVAL; return core::ptr::null_mut();
6143 }
6144 let flags = fmodeflags(mode);
6145 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6146 if fd < 0 { ERRNO = (-fd) as c_int; return core::ptr::null_mut(); }
6147 fdopen(fd as c_int, mode)
6148}
6149
6150#[no_mangle]
6151pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6152 if fd < 0 || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6153 let m = *mode;
6154 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6155 ERRNO = EINVAL; return core::ptr::null_mut();
6156 }
6157 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6158 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
6159 let buf = buf_ptr(f);
6160 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6161 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6162 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6163 if (*f).flags & F_NOWR == 0 {
6164 let mut ws: winsize = core::mem::zeroed();
6165 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6166 (*f).lbf = b'\n' as c_int;
6167 }
6168 }
6169 f
6170}
6171
6172#[no_mangle]
6173pub unsafe extern "C" fn freopen(
6174 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6175) -> *mut FILE {
6176 fflush(f);
6177 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6178 if filename.is_null() {
6179 let flags = fmodeflags(mode);
6180 if flags == 0 { return core::ptr::null_mut(); }
6181 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6182 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6183 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6184 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6185 if has_plus {
6186 (*f).flags &= !(F_NORD | F_NOWR);
6187 } else if *mode == b'r' as c_char {
6188 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6189 } else {
6190 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6191 }
6192 return f;
6193 }
6194 let new_f = fopen(filename, mode);
6195 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6196 if (*new_f).fd == (*f).fd {
6197 (*new_f).fd = -1;
6198 } else {
6199 sys_dup3((*new_f).fd, (*f).fd, 0);
6200 let _ = __stdio_close(new_f);
6201 }
6202 (*f).flags = (*new_f).flags;
6203 (*f).rpos = core::ptr::null_mut();
6204 (*f).rend = core::ptr::null_mut();
6205 (*f).wpos = core::ptr::null_mut();
6206 (*f).wbase = core::ptr::null_mut();
6207 (*f).wend = core::ptr::null_mut();
6208 (*f).lbf = (*new_f).lbf;
6209 (*f).pipe_pid = 0;
6210 free(new_f as *mut c_void);
6211 f
6212}
6213
6214#[no_mangle]
6215pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6216 if f.is_null() { return -1; }
6217 let r = fflush(f);
6218 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6219 if r != 0 { -1 } else { 0 }
6220}
6221
6222#[no_mangle]
6227pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6228 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6229 fflush(f);
6230 (*f).rpos = core::ptr::null_mut();
6231 (*f).rend = core::ptr::null_mut();
6232 (*f).wpos = core::ptr::null_mut();
6233 (*f).wbase = core::ptr::null_mut();
6234 (*f).wend = core::ptr::null_mut();
6235 if mode == _IONBF {
6236 (*f).buf_size = 0;
6237 } else if !buf.is_null() && size > 0 {
6238 (*f).buf = buf as *mut u8;
6239 (*f).buf_size = size;
6240 }
6241 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6242 0
6243}
6244
6245#[no_mangle]
6246pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6247 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6248 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6249}
6250
6251#[no_mangle]
6252pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6253 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6254 else { setvbuf(f, buf, _IOFBF, size); }
6255}
6256
6257#[no_mangle]
6258pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6259 if f.is_null() {
6260 let mut r = 0;
6261 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6262 if flush_buf(stdout) != 0 { r = -1; }
6263 }
6264 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6265 if flush_buf(stderr) != 0 { r = -1; }
6266 }
6267 return r;
6268 }
6269 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6270 return flush_buf(f);
6271 }
6272 0
6273}
6274
6275#[no_mangle]
6280pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6281
6282#[no_mangle]
6283pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6284
6285#[no_mangle]
6286pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6287
6288#[no_mangle]
6289pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6290
6291#[no_mangle]
6292pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6293
6294#[no_mangle]
6299pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6300 fseeko(stream, offset as i64, whence)
6301}
6302
6303#[no_mangle]
6304pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6305 ftello(stream) as c_long
6306}
6307
6308#[no_mangle]
6309pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6310 fseek(stream, 0, SEEK_SET);
6311 (*stream)._eof = 0;
6312 (*stream)._err = 0;
6313}
6314
6315#[no_mangle]
6316pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6317 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6318 ERRNO = EINVAL;
6319 return -1;
6320 }
6321 let f = &mut *stream;
6322 let mut adj_offset = offset;
6323 if whence == SEEK_CUR {
6324 if !f.rpos.is_null() {
6325 adj_offset -= f.rend as i64 - f.rpos as i64;
6326 }
6327 adj_offset -= f.ungotten_count as i64;
6328 }
6329 if !f.wpos.is_null() && f.wpos != f.wbase {
6330 if flush_buf(stream) != 0 { return -1; }
6331 }
6332 f.wpos = core::ptr::null_mut();
6333 f.wbase = core::ptr::null_mut();
6334 f.wend = core::ptr::null_mut();
6335 if let Some(sfunc) = f.seek_fn {
6336 let r = sfunc(stream, adj_offset, whence);
6337 if r < 0 { return -1; }
6338 } else {
6339 ERRNO = EINVAL;
6340 return -1;
6341 }
6342 f.rpos = core::ptr::null_mut();
6343 f.rend = core::ptr::null_mut();
6344 f._eof = 0;
6345 f.ungotten_count = 0;
6346 0
6347}
6348
6349#[no_mangle]
6350pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6351 let f = &mut *stream;
6352 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6353 if fflush(stream) != 0 { return -1; }
6354 }
6355 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6356 let pos = sfunc(stream, 0,
6357 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6358 if pos < 0 { return -1; }
6359 let mut pos = pos;
6360 if !f.rpos.is_null() {
6361 pos += f.rpos as i64 - f.rend as i64;
6362 } else if !f.wbase.is_null() {
6363 pos += f.wpos as i64 - f.wbase as i64;
6364 }
6365 pos - f.ungotten_count as i64
6366}
6367
6368#[no_mangle]
6369pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6370 let off = ftello(stream);
6371 if off < 0 { return -1; }
6372 *pos = off;
6373 0
6374}
6375
6376#[no_mangle]
6377pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6378 fseeko(stream, *pos, SEEK_SET)
6379}
6380
6381#[no_mangle]
6386pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6387 let f = &mut *stream;
6388 if f.ungotten_count > 0 {
6389 f.ungotten_count -= 1;
6390 return f.ungotten[f.ungotten_count as usize];
6391 }
6392 if !f.rpos.is_null() && f.rpos < f.rend {
6393 let c = *f.rpos;
6394 f.rpos = f.rpos.add(1);
6395 return c as c_int;
6396 }
6397 if f._eof != 0 { return -1; }
6398 if let Some(rfunc) = f.read_fn {
6399 let mut buf = [0u8; 1];
6400 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6401 if n == 0 {
6402 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6403 return -1;
6404 }
6405 buf[0] as c_int
6406 } else {
6407 f._eof = 1;
6408 -1
6409 }
6410}
6411
6412#[no_mangle]
6413pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6414
6415#[no_mangle]
6416pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6417
6418#[no_mangle]
6419pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6420 if c == -1 { return -1; }
6421 let f = &mut *stream;
6422 if f.ungotten_count >= UNGET as c_int { return -1; }
6423 f.ungotten[f.ungotten_count as usize] = c;
6424 f.ungotten_count += 1;
6425 f._eof = 0;
6426 c
6427}
6428
6429#[no_mangle]
6434pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6435 if n <= 0 { return null_mut(); }
6436 let max = (n - 1) as usize;
6437 let mut i = 0usize;
6438 while i < max {
6439 let c = fgetc(stream);
6440 if c == -1 { if i == 0 { return null_mut(); } break; }
6441 *s.add(i) = c as c_char;
6442 i += 1;
6443 if c == b'\n' as c_int { break; }
6444 }
6445 *s.add(i) = 0;
6446 s
6447}
6448
6449#[no_mangle]
6451pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6452 let mut i = 0usize;
6453 loop {
6454 let c = fgetc(stdin);
6455 if c == -1 { if i == 0 { return null_mut(); } break; }
6456 if c == b'\n' as c_int { break; }
6457 *s.add(i) = c as c_char;
6458 i += 1;
6459 }
6460 *s.add(i) = 0;
6461 s
6462}
6463
6464#[no_mangle]
6465pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6466 fopen(filename, mode)
6467}
6468
6469const PERROR_BUF_SIZE: usize = 64;
6471static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6472
6473#[no_mangle]
6474pub unsafe extern "C" fn perror(msg: *const c_char) {
6475 let fd = (*stderr).fd;
6476 if !msg.is_null() && *msg != 0 {
6477 let len = strlen(msg as *const c_char);
6478 write_str(fd, msg as *const u8, len);
6479 write_str(fd, b": ".as_ptr(), 2);
6480 }
6481 let e = ERRNO;
6482 if e != 0 {
6484 let (buf, len) = format_i64(e as i64);
6485 write_str(fd, buf.as_ptr().add(21 - len), len);
6486 }
6487 write_str(fd, b"\n".as_ptr(), 1);
6488}
6489
6490#[no_mangle]
6491pub unsafe extern "C" fn fread(
6492 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6493) -> SizeT {
6494 if size == 0 || nmemb == 0 { return 0; }
6495 let total = size * nmemb;
6496 let mut rd = 0usize;
6497 while rd < total {
6498 let c = fgetc(stream);
6499 if c == -1 { break; }
6500 *(ptr as *mut u8).add(rd) = c as u8;
6501 rd += 1;
6502 }
6503 rd / size
6504}
6505
6506unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6511 let mut written = 0usize;
6512 while written < len {
6513 let n = sys_write(fd as i64, s.add(written), len - written);
6514 if n <= 0 { break; }
6515 written += n as usize;
6516 }
6517}
6518
6519unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6520 if (*f).wpos.is_null() {
6521 (*f).wbase = (*f).buf;
6522 (*f).wpos = (*f).buf;
6523 (*f).wend = (*f).buf.add((*f).buf_size);
6524 }
6525 if flush_buf(f) == -1 { return -1; }
6526 if (*f).wpos >= (*f).wend {
6527 if let Some(wfunc) = (*f).write_fn {
6528 let byte = c as u8;
6529 let ret = wfunc(f, &byte as *const u8, 1);
6530 if ret == 0 { return -1; }
6531 }
6532 return c;
6533 }
6534 *(*f).wpos = c as u8;
6535 (*f).wpos = (*f).wpos.add(1);
6536 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6537 c
6538}
6539
6540#[no_mangle]
6541pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6542 let len = strlen(s as *const c_char);
6543 let _ = fwrite(s as *const c_void, 1, len, stdout);
6544 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6545 let f = &mut *stdout;
6546 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6547 (len + 1) as c_int
6548}
6549
6550#[no_mangle]
6551pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6552 let len = strlen(s as *const c_char);
6553 fwrite(s as *const c_void, 1, len, stream) as c_int
6554}
6555
6556#[no_mangle]
6557pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6558 let f = &mut *stream;
6559 if f.wpos.is_null() || f.wpos >= f.wend {
6560 if __overflow(f, c) == -1 { return -1; }
6561 return c;
6562 }
6563 *f.wpos = c as u8;
6564 f.wpos = f.wpos.add(1);
6565 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6566 c
6567}
6568
6569#[no_mangle]
6570pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6571
6572#[no_mangle]
6573pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6574
6575#[no_mangle]
6576pub unsafe extern "C" fn fwrite(
6577 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6578) -> SizeT {
6579 if size == 0 || nmemb == 0 { return 0; }
6580 let total = size * nmemb;
6581 let f = &mut *stream;
6582 if f.buf_size == 0 {
6583 if let Some(wfunc) = f.write_fn {
6584 let ret = wfunc(stream, ptr as *const u8, total);
6585 return ret / size;
6586 }
6587 return 0;
6588 }
6589 if f.wpos.is_null() {
6590 f.wbase = f.buf;
6591 f.wpos = f.buf;
6592 f.wend = f.buf.add(f.buf_size);
6593 }
6594 let mut remaining = total;
6595 let mut src = ptr as *const u8;
6596 while remaining > 0 {
6597 let space = f.wend as usize - f.wpos as usize;
6598 if space == 0 {
6599 if flush_buf(f as *mut FILE) == -1 { break; }
6600 continue;
6601 }
6602 let n = if remaining < space { remaining } else { space };
6603 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6604 f.wpos = f.wpos.add(n);
6605 src = src.add(n);
6606 remaining -= n;
6607 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6608 }
6609 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6610 (total - remaining) / size
6611}
6612
6613macro_rules! impl_format {
6618 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6619 let fmt = $fmt;
6620 let args = &mut $args;
6621 let mut count: usize = 0;
6622 let mut i = 0usize;
6623 loop {
6624 let c = *fmt.add(i) as u8;
6625 if c == 0 { break; }
6626 if c != b'%' {
6627 ($write_char)(c);
6628 count += 1; i += 1; continue;
6629 }
6630 i += 1;
6631 let mut flags: u8 = 0;
6633 loop {
6634 let fc = *fmt.add(i) as u8;
6635 match fc {
6636 b'-' => { flags |= FLAG_MINUS; i += 1; }
6637 b'+' => { flags |= FLAG_PLUS; i += 1; }
6638 b' ' => { flags |= FLAG_SPACE; i += 1; }
6639 b'0' => { flags |= FLAG_ZERO; i += 1; }
6640 b'#' => { flags |= FLAG_HASH; i += 1; }
6641 _ => break,
6642 }
6643 }
6644 let mut width: usize = 0;
6646 if *fmt.add(i) as u8 == b'*' {
6647 width = args.next_arg::<c_int>() as usize; i += 1;
6648 } else {
6649 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6650 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
6651 }
6652 }
6653 let mut precision: i32 = -1;
6655 if *fmt.add(i) as u8 == b'.' {
6656 i += 1;
6657 if *fmt.add(i) as u8 == b'*' {
6658 precision = args.next_arg::<c_int>(); i += 1;
6659 } else {
6660 precision = 0;
6661 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6662 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
6663 }
6664 }
6665 }
6666 let len_mod = *fmt.add(i) as u8;
6668 let spec: u8;
6669 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
6670 i += 1;
6671 let len_mod2 = *fmt.add(i) as u8;
6672 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
6673 i += 1;
6674 spec = *fmt.add(i) as u8;
6675 match (len_mod, len_mod2, spec) {
6677 (b'h', b'h', b'n') => {
6678 let p = args.next_arg::<*mut c_void>();
6679 if !p.is_null() { *(p as *mut u8) = count as u8; }
6680 }
6681 (b'l', b'l', b'n') => {
6682 let p = args.next_arg::<*mut c_void>();
6683 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
6684 }
6685 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
6686 let val = args.next_arg::<c_longlong>();
6687 let neg = val < 0;
6688 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6689 let b = format_u64(abs);
6690 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6691 let mut fbuf = [0u8; 32];
6692 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6693 ($write_str)(fbuf.as_ptr(), len); count += len;
6694 }
6695 (b'l', b'l', b'u') => {
6696 let val = args.next_arg::<c_ulonglong>();
6697 let b = format_u64(val as u64);
6698 let mut fbuf = [0u8; 32];
6699 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6700 ($write_str)(fbuf.as_ptr(), len); count += len;
6701 }
6702 (b'l', b'l', b'o') => {
6703 let val = args.next_arg::<c_ulonglong>();
6704 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6705 let mut fbuf = [0u8; 32];
6706 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6707 ($write_str)(fbuf.as_ptr(), len); count += len;
6708 }
6709 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
6710 }
6711 } else {
6712 spec = len_mod2;
6713 match (len_mod, spec) {
6714 (b'h', b'n') => {
6715 let p = args.next_arg::<*mut c_void>();
6716 if !p.is_null() { *(p as *mut u16) = count as u16; }
6717 }
6718 (b'l', b'n') => {
6719 let p = args.next_arg::<*mut c_void>();
6720 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
6721 }
6722 (b'z', b'n') | (b't', b'n') => {
6723 let p = args.next_arg::<*mut c_void>();
6724 if !p.is_null() { *(p as *mut usize) = count; }
6725 }
6726 (b'j', b'n') => {
6727 let p = args.next_arg::<*mut c_void>();
6728 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
6729 }
6730 (b'l', b'd') | (b'l', b'i') => {
6731 let val = args.next_arg::<c_long>();
6732 let neg = val < 0;
6733 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6734 let b = format_u64(abs);
6735 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6736 let mut fbuf = [0u8; 32];
6737 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6738 ($write_str)(fbuf.as_ptr(), len); count += len;
6739 }
6740 (b'l', b'u') => {
6741 let val = args.next_arg::<c_ulong>();
6742 let b = format_u64(val as u64);
6743 let mut fbuf = [0u8; 32];
6744 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6745 ($write_str)(fbuf.as_ptr(), len); count += len;
6746 }
6747 (b'l', b'x') => {
6748 let val = args.next_arg::<c_ulong>();
6749 let b = format_hex(val as u64, false);
6750 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6751 let mut fbuf = [0u8; 32];
6752 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6753 ($write_str)(fbuf.as_ptr(), len); count += len;
6754 }
6755 (b'l', b'X') => {
6756 let val = args.next_arg::<c_ulong>();
6757 let b = format_hex(val as u64, true);
6758 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6759 let mut fbuf = [0u8; 32];
6760 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6761 ($write_str)(fbuf.as_ptr(), len); count += len;
6762 }
6763 (b'l', b'o') => {
6764 let val = args.next_arg::<c_ulong>();
6765 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6766 let mut fbuf = [0u8; 32];
6767 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6768 ($write_str)(fbuf.as_ptr(), len); count += len;
6769 }
6770 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
6771 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
6772 let val = args.next_arg::<f64>();
6773 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6774 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6775 let mut fbuf = [0u8; 4224];
6776 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6777 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6778 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6779 ($write_str)(fbuf.as_ptr(), total); count += total;
6780 }
6781 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
6782 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
6783 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
6784 let val = {
6785 let lo: u64 = args.next_arg::<u64>();
6786 let hi: u64 = args.next_arg::<u64>();
6787 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
6788 f128::from_bits(combined) as f64
6789 };
6790 #[cfg(target_arch = "x86_64")]
6791 let val = args.next_arg::<f64>();
6792 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6793 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6794 let mut fbuf = [0u8; 4224];
6795 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6796 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6797 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6798 ($write_str)(fbuf.as_ptr(), total); count += total;
6799 }
6800 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
6801 }
6802 }
6803 } else {
6804 spec = *fmt.add(i) as u8;
6805 match spec {
6806 b's' => {
6807 let s = args.next_arg::<*const c_char>();
6808 if s.is_null() {
6809 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
6810 let padded_len = if width > slen { width } else { slen };
6811 let pad = padded_len - slen;
6812 if flags & FLAG_MINUS != 0 {
6813 ($write_str)(b"(null)".as_ptr(), slen);
6814 for _ in 0..pad { ($write_char)(b' '); }
6815 } else {
6816 for _ in 0..pad { ($write_char)(b' '); }
6817 ($write_str)(b"(null)".as_ptr(), slen);
6818 }
6819 count += padded_len;
6820 } else {
6821 let full_len = strlen(s as *const c_char);
6822 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
6823 let padded_len = if width > slen { width } else { slen };
6824 let pad = padded_len - slen;
6825 if flags & FLAG_MINUS != 0 {
6826 ($write_str)(s as *const u8, slen);
6827 for _ in 0..pad { ($write_char)(b' '); }
6828 } else {
6829 for _ in 0..pad { ($write_char)(b' '); }
6830 ($write_str)(s as *const u8, slen);
6831 }
6832 count += padded_len;
6833 }
6834 }
6835 b'd' | b'i' => {
6836 let d = args.next_arg::<c_int>();
6837 let neg = d < 0;
6838 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
6839 let b = format_u64(abs);
6840 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6841 let mut fbuf = [0u8; 32];
6842 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6843 ($write_str)(fbuf.as_ptr(), len); count += len;
6844 }
6845 b'u' => {
6846 let u = args.next_arg::<c_uint>();
6847 let b = format_u64(u as u64);
6848 let mut fbuf = [0u8; 32];
6849 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6850 ($write_str)(fbuf.as_ptr(), len); count += len;
6851 }
6852 b'x' => {
6853 let x = args.next_arg::<c_uint>();
6854 let b = format_hex(x as u64, false);
6855 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6856 let mut fbuf = [0u8; 32];
6857 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6858 ($write_str)(fbuf.as_ptr(), len); count += len;
6859 }
6860 b'X' => {
6861 let x = args.next_arg::<c_uint>();
6862 let b = format_hex(x as u64, true);
6863 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6864 let mut fbuf = [0u8; 32];
6865 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6866 ($write_str)(fbuf.as_ptr(), len); count += len;
6867 }
6868 b'o' => {
6869 let o = args.next_arg::<c_uint>();
6870 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
6871 let mut fbuf = [0u8; 32];
6872 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6873 ($write_str)(fbuf.as_ptr(), len); count += len;
6874 }
6875 b'c' => {
6876 let ch = args.next_arg::<c_int>();
6877 if width > 1 {
6878 let pad = width - 1;
6879 if flags & FLAG_MINUS != 0 {
6880 ($write_char)(ch as u8); count += 1;
6881 for _ in 0..pad { ($write_char)(b' '); count += 1; }
6882 } else {
6883 for _ in 0..pad { ($write_char)(b' '); count += 1; }
6884 ($write_char)(ch as u8); count += 1;
6885 }
6886 } else {
6887 ($write_char)(ch as u8); count += 1;
6888 }
6889 }
6890 b'p' => {
6891 let p = args.next_arg::<*const c_void>();
6892 let mut fbuf = [0u8; 20];
6893 fbuf[0] = b'0'; fbuf[1] = b'x';
6894 let b = format_hex(p as u64, false);
6895 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
6896 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
6897 }
6898 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
6899 let val = args.next_arg::<f64>();
6900 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6901 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6902 let mut fbuf = [0u8; 4224];
6903 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6904 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6905 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6906 ($write_str)(fbuf.as_ptr(), total); count += total;
6907 }
6908 b'%' => { ($write_char)(b'%'); count += 1; }
6909 b'n' => {
6910 let p = args.next_arg::<*mut c_void>();
6911 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
6912 }
6913 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
6914 }
6915 }
6916 i += 1;
6917 }
6918 count as c_int
6919 }};
6920}
6921
6922unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
6923 let mut buf = [0u8; 20];
6924 if val == 0 { buf[0] = b'0'; return (buf, 1); }
6925 let mut tmp = [0u8; 20];
6926 let mut pos = 20;
6927 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
6928 let len = 20 - pos;
6929 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6930 (buf, len)
6931}
6932
6933unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
6934 let mut buf = [0u8; 21];
6935 if val < 0 {
6936 buf[0] = b'-';
6937 let (inner, len) = format_u64((-(val as i128)) as u64);
6938 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
6939 (buf, len + 1)
6940 } else {
6941 let (inner, len) = format_u64(val as u64);
6942 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
6943 (buf, len)
6944 }
6945}
6946
6947unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
6948 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
6949 let mut buf = [0u8; 16];
6950 if val == 0 { buf[0] = b'0'; return (buf, 1); }
6951 let mut tmp = [0u8; 16];
6952 let mut pos = 16;
6953 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
6954 let len = 16 - pos;
6955 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6956 (buf, len)
6957}
6958
6959unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
6960 let mut buf = [0u8; 24];
6961 if val == 0 {
6962 buf[0] = b'0';
6963 return (buf, 1);
6964 }
6965 let mut tmp = [0u8; 24];
6966 let mut pos = 24;
6967 while val > 0 {
6968 pos -= 1;
6969 tmp[pos] = b'0' + (val & 7) as u8;
6970 val >>= 3;
6971 }
6972 let len = 24 - pos;
6973 if alt {
6974 tmp[pos - 1] = b'0';
6975 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
6976 (buf, len + 1)
6977 } else {
6978 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6979 (buf, len)
6980 }
6981}
6982
6983unsafe fn format_int(
6984 dst: *mut u8,
6985 digits: *const u8,
6986 digits_len: usize,
6987 sign: Option<u8>,
6988 prefix: Option<u8>,
6989 precision: i32,
6990 width: usize,
6991 flags: u8,
6992 octal_alt: bool,
6993) -> usize {
6994 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
6995 0
6996 } else {
6997 digits_len
6998 };
6999 let prec = precision as usize;
7000 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7001
7002 let sign_len = sign.map_or(0, |_| 1);
7003 let prefix_len = prefix.map_or(0, |_| 2);
7004 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7005
7006 let mut buf = [0u8; 32];
7007 let mut pos = 0usize;
7008 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7009 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7010 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7011 if num_digits > 0 {
7012 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7013 }
7014
7015 if content_len >= width {
7016 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7017 return content_len;
7018 }
7019 let pad = width - content_len;
7020 if flags & FLAG_MINUS != 0 {
7021 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7022 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7023 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7024 let fixed = sign_len + prefix_len;
7025 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7026 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7027 if num_digits > 0 {
7028 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7029 }
7030 } else {
7031 for i in 0..pad { *dst.add(i) = b' '; }
7032 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7033 }
7034 width
7035}
7036
7037unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7038 let mut buf = [0u8; 64];
7039 let mut pos = 0usize;
7040 let mut v = val;
7041 if v.is_nan() {
7042 let nan = b"nan";
7043 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7044 return (buf, 3);
7045 }
7046 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7047 if v.is_infinite() {
7048 let inf = b"inf";
7049 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7050 return (buf, pos + 3);
7051 }
7052 let int_part = v as u64;
7053 let frac = v - int_part as f64;
7054 let (ibuf, ilen) = format_u64(int_part);
7055 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7056 pos += ilen;
7057 buf[pos] = b'.';
7058 pos += 1;
7059 let mut f = frac;
7060 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7061 (buf, pos)
7062}
7063
7064const FMT_F: u8 = 0;
7066const FMT_E: u8 = 1;
7067const FMT_G: u8 = 2;
7068const FMT_A: u8 = 3;
7069
7070const FLAG_HASH: u8 = 1;
7071const FLAG_PLUS: u8 = 2;
7072const FLAG_SPACE: u8 = 4;
7073const FLAG_ZERO: u8 = 8;
7074const FLAG_MINUS: u8 = 16;
7075
7076unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7081 let nlimbs = (2 + (shift + 31) / 32) as usize;
7083 let mut limbs = [0u32; 36];
7084 limbs[0] = mant as u32;
7085 limbs[1] = (mant >> 32) as u32;
7086
7087 let ws = (shift / 32) as usize;
7088 let bs = shift % 32;
7089
7090 if ws > 0 {
7092 let mut i = 1usize;
7093 loop {
7094 limbs[i + ws] = limbs[i];
7095 if i == 0 { break; }
7096 i -= 1;
7097 }
7098 for j in 0..ws { limbs[j] = 0; }
7099 }
7100 if bs > 0 {
7102 let mut carry = 0u32;
7103 let end = nlimbs.min(ws + 3);
7104 for i in ws..end {
7105 let new_val = (limbs[i] << bs) | carry;
7106 carry = limbs[i] >> (32 - bs);
7107 limbs[i] = new_val;
7108 }
7109 }
7110
7111 let mut used = nlimbs;
7113 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7114 if used == 0 { *buf = b'0'; return 1; }
7115
7116 let mut digits = [0u8; 400];
7118 let mut nd = 0usize;
7119 loop {
7120 let mut all_zero = true;
7121 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7122 if all_zero { break; }
7123 let mut rem = 0u64;
7124 for i in (0..used).rev() {
7125 let val = (rem << 32) | limbs[i] as u64;
7126 limbs[i] = (val / 10) as u32;
7127 rem = val % 10;
7128 }
7129 digits[nd] = rem as u8;
7130 nd += 1;
7131 }
7132 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7134 nd
7135}
7136
7137unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7140 let mask: u128 = (1u128 << shift) - 1;
7141 let mut rem = frac_bits as u128;
7142 for i in 0..count {
7143 rem *= 10;
7144 let digit = (rem >> shift) as u8;
7145 rem &= mask;
7146 *buf.add(i) = digit;
7147 }
7148 rem != 0
7149}
7150
7151unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7154 let nlimbs = ((shift + 31) / 32) as usize;
7155 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7157 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7158 let hi_word = (shift / 32) as usize;
7160 let hi_bit = shift % 32;
7161 if hi_bit > 0 && hi_word < nlimbs {
7162 rem[hi_word] &= (1u32 << hi_bit) - 1;
7163 }
7164 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7166 for j in clear_from..nlimbs { rem[j] = 0; }
7167
7168 for i in 0..count {
7169 let mut carry = 0u64;
7171 for j in 0..nlimbs {
7172 let val = rem[j] as u64 * 10 + carry;
7173 rem[j] = val as u32;
7174 carry = val >> 32;
7175 }
7176 let digit: u32;
7178 if hi_bit == 0 {
7179 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7180 } else {
7181 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7182 if hi_word + 1 < nlimbs {
7183 d |= rem[hi_word + 1] << (32 - hi_bit);
7184 } else if carry > 0 {
7185 d |= (carry as u32) << (32 - hi_bit);
7186 }
7187 digit = d;
7188 }
7189 *buf.add(i) = digit.min(9) as u8;
7190 if hi_bit == 0 {
7192 if hi_word < nlimbs { rem[hi_word] = 0; }
7193 } else {
7194 if hi_word < nlimbs {
7195 rem[hi_word] &= (1u32 << hi_bit) - 1;
7196 }
7197 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7198 }
7199 }
7200 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7202 false
7203}
7204
7205unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7207 let mut j = *len;
7208 loop {
7209 if j == 0 {
7210 let l = *len;
7212 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7213 *buf = b'1';
7214 *len = l + 1;
7215 return;
7216 }
7217 j -= 1;
7218 let d = *buf.add(j);
7219 if d < b'9' { *buf.add(j) = d + 1; return; }
7220 *buf.add(j) = b'0';
7221 }
7222}
7223
7224unsafe fn format_f64_full(
7226 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7227) -> usize {
7228 let mut pos = 0usize;
7229
7230 if val.is_nan() {
7232 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7233 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7234 return 3;
7235 }
7236 let neg = val.is_sign_negative();
7237 let v = if neg { -val } else { val };
7238
7239 if v.is_infinite() {
7241 if neg { *dst.add(pos) = b'-'; pos += 1; }
7242 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7243 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7244 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7245 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7246 return pos + 3;
7247 }
7248
7249 if neg { *dst.add(pos) = b'-'; pos += 1; }
7251 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7252 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7253
7254 if fmt_type == FMT_A {
7256 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7257 }
7258
7259 let p: usize;
7261 let mut exp: i32;
7262 let use_f: bool;
7263
7264 match fmt_type {
7265 FMT_G => {
7266 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7267 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7268 use_f = exp >= -4 && exp < gp as i32;
7269 if use_f {
7270 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7271 else if (exp as usize) < gp { gp - exp as usize - 1 }
7272 else { 0 };
7273 } else {
7274 p = gp - 1;
7275 }
7276 }
7277 FMT_E => {
7278 p = if precision < 0 { 6usize } else { precision as usize };
7279 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7280 use_f = false;
7281 }
7282 _ => {
7283 p = if precision < 0 { 6usize } else { precision as usize };
7284 exp = 0;
7285 use_f = true;
7286 }
7287 }
7288
7289 if v == 0.0 {
7290 *dst.add(pos) = b'0'; pos += 1;
7291 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7292 if p > 0 || flags & FLAG_HASH != 0 {
7293 *dst.add(pos) = b'.'; pos += 1;
7294 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7295 }
7296 }
7297 if !use_f {
7298 let ec = if uppercase { b'E' } else { b'e' };
7299 *dst.add(pos) = ec; pos += 1;
7300 *dst.add(pos) = b'+'; pos += 1;
7301 *dst.add(pos) = b'0'; pos += 1;
7302 *dst.add(pos) = b'0'; pos += 1;
7303 }
7304 return pos;
7305 }
7306
7307 if use_f {
7309 let bits = v.to_bits();
7310 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7311 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7312 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7313 (raw_mant, -1022i32)
7314 } else {
7315 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7316 };
7317
7318 let mut ibuf = [0u8; 400];
7320 let mut ilen: usize;
7321 if bin_exp < 0 {
7322 ibuf[0] = b'0'; ilen = 1;
7323 } else if bin_exp <= 63 {
7324 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7325 else { mant_b << (bin_exp - 52) };
7326 let (buf2, len2) = format_u64(int_val);
7327 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7328 ilen = len2;
7329 } else {
7330 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7331 }
7332
7333 let mut fbuf = [0u8; 1100];
7335 let mut has_rest = false;
7336 if p > 0 && bin_exp < 52 {
7337 let shift = (52 - bin_exp) as u32;
7338 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7339 if shift <= 124 {
7340 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7341 } else {
7342 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7343 }
7344 }
7345
7346 if p > 0 && bin_exp < 52 {
7348 let next_d = fbuf[p];
7349 let last_d = fbuf[p - 1];
7350 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7351 let mut carry = true;
7352 for j in (0..p).rev() {
7353 if !carry { break; }
7354 fbuf[j] += 1;
7355 if fbuf[j] < 10 { carry = false; break; }
7356 fbuf[j] = 0;
7357 }
7358 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7359 }
7360 } else if p == 0 {
7361 if bin_exp >= 0 && bin_exp < 52 {
7363 let shift = (52 - bin_exp) as u32;
7364 let frac_bits = mant_b & ((1u64 << shift) - 1);
7365 let half = 1u64 << (shift - 1);
7366 let last_d = ibuf[ilen - 1] - b'0';
7367 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7368 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7369 }
7370 }
7371 }
7372
7373 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7375 pos += ilen;
7376 if p > 0 || flags & FLAG_HASH != 0 {
7377 *dst.add(pos) = b'.'; pos += 1;
7378 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7379 }
7380 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7381 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7382 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7383 }
7384 return pos;
7385 }
7386
7387 let mut fbuf = [0u8; 20];
7390 let mut int_part: u64;
7391 {
7392 let bits_v = v.to_bits();
7393 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7394 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7395 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7396 (raw_mant_v, -1022i32)
7397 } else {
7398 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7399 };
7400
7401 let s: i32 = (p as i32) + 1 - exp;
7402 let bs: i32 = bin_exp_v - 52 + s;
7403
7404 let mut limbs = [0u32; 40];
7405 limbs[0] = mant_b_v as u32;
7406 limbs[1] = (mant_b_v >> 32) as u32;
7407 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7408
7409 if s > 0 {
7410 for _ in 0..(s as usize) {
7411 let mut carry = 0u64;
7412 for j in 0..nlimbs {
7413 let val = limbs[j] as u64 * 5 + carry;
7414 limbs[j] = val as u32;
7415 carry = val >> 32;
7416 }
7417 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7418 }
7419 }
7420
7421 if bs > 0 {
7422 let ws = (bs as u32 / 32) as usize;
7423 let bit = bs as u32 % 32;
7424 if ws > 0 {
7425 let mut i = nlimbs;
7426 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7427 nlimbs += ws;
7428 }
7429 if bit > 0 {
7430 let mut carry = 0u32;
7431 for i in ws..nlimbs {
7432 let new_val = (limbs[i] << bit) | carry;
7433 carry = limbs[i] >> (32 - bit);
7434 limbs[i] = new_val;
7435 }
7436 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7437 }
7438 }
7439
7440 let mut has_rest = false;
7441 if s < 0 {
7442 for _ in 0..(-s as usize) {
7443 let mut rem = 0u64;
7444 for i in (0..nlimbs).rev() {
7445 let val = (rem << 32) | limbs[i] as u64;
7446 limbs[i] = (val / 5) as u32;
7447 rem = val % 5;
7448 }
7449 if rem != 0 { has_rest = true; }
7450 }
7451 }
7452
7453 if bs < 0 {
7454 let rshift = (-bs) as u32;
7455 let ws = (rshift / 32) as usize;
7456 let bit = rshift % 32;
7457 if ws > 0 {
7458 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7459 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7460 nlimbs = nlimbs.saturating_sub(ws);
7461 }
7462 if bit > 0 && nlimbs > 0 {
7463 let mask = (1u32 << bit) - 1;
7464 if limbs[0] & mask != 0 { has_rest = true; }
7465 for i in 0..nlimbs - 1 {
7466 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7467 }
7468 limbs[nlimbs - 1] >>= bit;
7469 }
7470 }
7471
7472 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7473
7474 let ndigits = p + 2;
7475 let mut all_digits = [0u8; 25];
7476 let mut nd = 0usize;
7477 if nlimbs > 0 {
7478 loop {
7479 let mut all_zero = true;
7480 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7481 if all_zero { break; }
7482 let mut rem64 = 0u64;
7483 for i in (0..nlimbs).rev() {
7484 let val = (rem64 << 32) | limbs[i] as u64;
7485 limbs[i] = (val / 10) as u32;
7486 rem64 = val % 10;
7487 }
7488 if nd < 25 { all_digits[nd] = rem64 as u8; }
7489 nd += 1;
7490 }
7491 }
7492
7493 if nd >= ndigits {
7494 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7495 } else {
7496 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7497 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7498 }
7499
7500 int_part = fbuf[0] as u64;
7501
7502 if p > 0 {
7504 let next_d = fbuf[p + 1];
7505 let last_d = fbuf[p];
7506 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7507 let mut carry = true;
7508 for j in (1..=p).rev() {
7509 if !carry { break; }
7510 let d = fbuf[j] + 1;
7511 if d < 10 { fbuf[j] = d; carry = false; break; }
7512 fbuf[j] = 0;
7513 }
7514 if carry { int_part += 1; }
7515 }
7516 } else {
7517 let next_d = fbuf[1];
7518 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7519 int_part += 1;
7520 }
7521 }
7522
7523 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7526 }
7527
7528 if !use_f && int_part >= 10 {
7529 exp += 1;
7530 int_part = 1;
7531 }
7532
7533 if use_f {
7535 let (ibuf, ilen) = format_u64(int_part);
7537 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7538 pos += ilen;
7539 if p > 0 || flags & FLAG_HASH != 0 {
7540 *dst.add(pos) = b'.'; pos += 1;
7541 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7542 }
7543 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7544 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7545 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7546 }
7547 } else {
7548 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7550 if p > 0 || flags & FLAG_HASH != 0 {
7551 *dst.add(pos) = b'.'; pos += 1;
7552 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7553 }
7554 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7555 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7556 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7557 }
7558 let ec = if uppercase { b'E' } else { b'e' };
7559 *dst.add(pos) = ec; pos += 1;
7560 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7561 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7562 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7563 let (ebuf, elen) = format_u64(eabs as u64);
7564 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7565 pos += elen;
7566 }
7567
7568 pos
7569}
7570
7571unsafe fn compute_exp10(v: f64) -> i32 {
7573 let e = libm::floor(libm::log10(v)) as i32;
7574 let probe = v / libm::pow(10.0, e as f64);
7575 if probe >= 10.0 { e + 1 }
7576 else if probe < 1.0 { e - 1 }
7577 else { e }
7578}
7579
7580unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
7582 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
7584 let lc = !uppercase;
7585 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7586 let p = if precision < 0 { 0usize } else { precision as usize };
7587 let mut pos = 0usize;
7588 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7589 *dst.add(pos) = b'0'; pos += 1;
7590 if p > 0 {
7591 *dst.add(pos) = b'.'; pos += 1;
7592 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7593 }
7594 let pc = if lc { b'p' } else { b'P' };
7595 *dst.add(pos) = pc; pos += 1;
7596 *dst.add(pos) = b'+'; pos += 1;
7597 *dst.add(pos) = b'0'; pos += 1;
7598 return pos;
7599 }
7600 let bits = val.to_bits();
7601 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
7602 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
7603 let (e, m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
7604 let p = if precision < 0 { 13usize } else { precision as usize };
7605 let mut pos = 0usize;
7606 let lc = !uppercase;
7607 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7608 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7609
7610 let lead = ((m >> 52) & 0xF) as u8;
7612 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
7613 if p > 0 {
7614 *dst.add(pos) = b'.'; pos += 1;
7615 }
7616
7617 let frac_start = pos;
7619 let mut rm = m << 4; for _ in 0..p {
7621 let nib = ((rm >> 48) & 0xF) as u8;
7622 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
7623 rm <<= 4;
7624 }
7625
7626 if p > 0 {
7628 let round_nib = ((rm >> 48) & 0xF) as u8;
7629 let rest = rm & 0x0000FFFFFFFFFFFF;
7630 let last_nib = if p > 0 {
7631 let c = *dst.add(pos - 1);
7632 hex_char_val(c)
7633 } else { lead };
7634 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
7635 if should_round {
7636 let mut j = pos - 1;
7637 loop {
7638 if j < frac_start { break; }
7639 let v = hex_char_val(*dst.add(j));
7640 if v < 15 {
7641 *dst.add(j) = hex_digit_char(v + 1, lc);
7642 break;
7643 } else {
7644 *dst.add(j) = b'0';
7645 if j == frac_start { break; }
7646 j -= 1;
7647 }
7648 }
7649 }
7650 }
7651
7652 let pc = if lc { b'p' } else { b'P' };
7654 *dst.add(pos) = pc; pos += 1;
7655 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
7656 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
7657 let (ebuf, elen) = format_u64(eabs as u64);
7658 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7659 pos += elen;
7660 pos
7661}
7662
7663#[inline]
7664fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
7665 if v < 10 { b'0' + v }
7666 else if lowercase { b'a' + v - 10 }
7667 else { b'A' + v - 10 }
7668}
7669
7670#[inline]
7671fn hex_char_val(c: u8) -> u8 {
7672 if c >= b'0' && c <= b'9' { c - b'0' }
7673 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
7674 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
7675 else { 0 }
7676}
7677
7678unsafe fn apply_width_flags(
7681 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
7682) -> usize {
7683 if len >= width {
7684 core::ptr::copy_nonoverlapping(buf, dst, len);
7685 return len;
7686 }
7687 let pad = width - len;
7688 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
7689 if flags & FLAG_MINUS != 0 {
7690 core::ptr::copy_nonoverlapping(buf, dst, len);
7692 for i in 0..pad { *dst.add(len + i) = pad_char; }
7693 } else {
7694 if flags & FLAG_ZERO != 0 && len > 0 {
7697 let first = *buf;
7698 if first == b'-' || first == b'+' || first == b' ' {
7699 *dst = first;
7700 for i in 0..pad { *dst.add(1 + i) = pad_char; }
7701 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
7702 return width;
7703 }
7704 }
7705 for i in 0..pad { *dst.add(i) = pad_char; }
7706 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
7707 }
7708 width
7709}
7710
7711#[no_mangle]
7712pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
7713 impl_format!(fmt, args,
7714 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7715 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7716 )
7717}
7718
7719#[no_mangle]
7720pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
7721 impl_format!(fmt, args,
7722 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7723 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7724 )
7725}
7726
7727#[no_mangle]
7728pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
7729 impl_format!(fmt, args,
7730 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7731 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7732 )
7733}
7734
7735#[no_mangle]
7736pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
7737 impl_format!(fmt, args,
7738 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7739 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7740 )
7741}
7742
7743#[no_mangle]
7744pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
7745 impl_format!(fmt, args,
7746 |c: u8| { write_str(fd, &c as *const u8, 1); },
7747 |s: *const u8, len: usize| { write_str(fd, s, len); }
7748 )
7749}
7750
7751#[no_mangle]
7752pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
7753 impl_format!(fmt, args,
7754 |c: u8| { write_str(fd, &c as *const u8, 1); },
7755 |s: *const u8, len: usize| { write_str(fd, s, len); }
7756 )
7757}
7758
7759unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
7764 let mut pos = 0usize;
7765 let mut i = 0usize;
7766 let mut count = 0usize;
7767 macro_rules! wc {
7768 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
7769 }
7770 macro_rules! ws {
7771 ($s:expr, $len:expr) => {{
7772 let __len = $len;
7773 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
7774 pos += __len; count += __len;
7775 }}
7776 }
7777 macro_rules! ws_buf {
7779 ($src:expr, $len:expr) => {{
7780 let __len = $len;
7781 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
7782 pos += __len; count += __len;
7783 }}
7784 }
7785 loop {
7786 let c = *fmt.add(i) as u8;
7787 if c == 0 { break; }
7788 if c != b'%' { wc!(c); i += 1; continue; }
7789 i += 1;
7790 let mut flags: u8 = 0;
7792 loop {
7793 let fc = *fmt.add(i) as u8;
7794 match fc {
7795 b'-' => { flags |= FLAG_MINUS; i += 1; }
7796 b'+' => { flags |= FLAG_PLUS; i += 1; }
7797 b' ' => { flags |= FLAG_SPACE; i += 1; }
7798 b'0' => { flags |= FLAG_ZERO; i += 1; }
7799 b'#' => { flags |= FLAG_HASH; i += 1; }
7800 _ => break,
7801 }
7802 }
7803 let mut width: usize = 0;
7805 if *fmt.add(i) as u8 == b'*' {
7806 width = args.next_arg::<c_int>() as usize; i += 1;
7807 } else {
7808 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7809 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
7810 }
7811 }
7812 let mut precision: i32 = -1;
7814 if *fmt.add(i) as u8 == b'.' {
7815 i += 1;
7816 if *fmt.add(i) as u8 == b'*' {
7817 precision = args.next_arg::<c_int>(); i += 1;
7818 } else {
7819 precision = 0;
7820 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7821 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
7822 }
7823 }
7824 }
7825 let len_mod = *fmt.add(i) as u8;
7827 let spec: u8;
7828 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
7829 i += 1;
7830 let len_mod2 = *fmt.add(i) as u8;
7831 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
7832 i += 1;
7833 spec = *fmt.add(i) as u8;
7834 match (len_mod, len_mod2, spec) {
7835 (b'h', b'h', b'n') => {
7836 let p = args.next_arg::<*mut c_void>();
7837 if !p.is_null() { *(p as *mut u8) = count as u8; }
7838 }
7839 (b'l', b'l', b'n') => {
7840 let p = args.next_arg::<*mut c_void>();
7841 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
7842 }
7843 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
7844 let val = args.next_arg::<c_longlong>();
7845 let neg = val < 0;
7846 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7847 let b = format_u64(abs);
7848 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7849 let mut fbuf = [0u8; 32];
7850 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7851 ws_buf!(fbuf.as_ptr(), len);
7852 }
7853 (b'l', b'l', b'u') => {
7854 let val = args.next_arg::<c_ulonglong>();
7855 let b = format_u64(val as u64);
7856 let mut fbuf = [0u8; 32];
7857 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7858 ws_buf!(fbuf.as_ptr(), len);
7859 }
7860 (b'l', b'l', b'o') => {
7861 let val = args.next_arg::<c_ulonglong>();
7862 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7863 let mut fbuf = [0u8; 32];
7864 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7865 ws_buf!(fbuf.as_ptr(), len);
7866 }
7867 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
7868 }
7869 } else {
7870 spec = len_mod2;
7871 match (len_mod, spec) {
7872 (b'h', b'n') => {
7873 let p = args.next_arg::<*mut c_void>();
7874 if !p.is_null() { *(p as *mut u16) = count as u16; }
7875 }
7876 (b'l', b'n') => {
7877 let p = args.next_arg::<*mut c_void>();
7878 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
7879 }
7880 (b'z', b'n') | (b't', b'n') => {
7881 let p = args.next_arg::<*mut c_void>();
7882 if !p.is_null() { *(p as *mut usize) = count; }
7883 }
7884 (b'j', b'n') => {
7885 let p = args.next_arg::<*mut c_void>();
7886 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
7887 }
7888 (b'l', b'd') | (b'l', b'i') => {
7889 let val = args.next_arg::<c_long>();
7890 let neg = val < 0;
7891 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7892 let b = format_u64(abs);
7893 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7894 let mut fbuf = [0u8; 32];
7895 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7896 ws_buf!(fbuf.as_ptr(), len);
7897 }
7898 (b'l', b'u') => {
7899 let val = args.next_arg::<c_ulong>();
7900 let b = format_u64(val as u64);
7901 let mut fbuf = [0u8; 32];
7902 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7903 ws_buf!(fbuf.as_ptr(), len);
7904 }
7905 (b'l', b'x') => {
7906 let val = args.next_arg::<c_ulong>();
7907 let b = format_hex(val as u64, false);
7908 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7909 let mut fbuf = [0u8; 32];
7910 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7911 ws_buf!(fbuf.as_ptr(), len);
7912 }
7913 (b'l', b'X') => {
7914 let val = args.next_arg::<c_ulong>();
7915 let b = format_hex(val as u64, true);
7916 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7917 let mut fbuf = [0u8; 32];
7918 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7919 ws_buf!(fbuf.as_ptr(), len);
7920 }
7921 (b'l', b'o') => {
7922 let val = args.next_arg::<c_ulong>();
7923 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7924 let mut fbuf = [0u8; 32];
7925 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7926 ws_buf!(fbuf.as_ptr(), len);
7927 }
7928 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7929 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7930 let val = args.next_arg::<f64>();
7931 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7932 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7933 let mut fbuf = [0u8; 4224];
7934 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7935 let mut wbuf = [0u8; 4224];
7936 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
7937 ws_buf!(wbuf.as_ptr(), wlen);
7938 }
7939 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7940 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7941 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7942 let val = {
7943 let lo: u64 = args.next_arg::<u64>();
7944 let hi: u64 = args.next_arg::<u64>();
7945 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7946 f128::from_bits(combined) as f64
7947 };
7948 #[cfg(target_arch = "x86_64")]
7949 let val = args.next_arg::<f64>();
7950 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7951 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7952 let mut fbuf = [0u8; 4224];
7953 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7954 let mut wbuf = [0u8; 4224];
7955 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
7956 ws_buf!(wbuf.as_ptr(), wlen);
7957 }
7958 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
7959 }
7960 }
7961 } else {
7962 spec = *fmt.add(i) as u8;
7963 match spec {
7964 b's' => {
7965 let s = args.next_arg::<*const c_char>();
7966 if s.is_null() {
7967 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7968 let padded_len = if width > slen { width } else { slen };
7969 let pad = padded_len - slen;
7970 if flags & FLAG_MINUS != 0 {
7971 ws!(b"(null)".as_ptr(), slen);
7972 for _ in 0..pad { wc!(b' '); }
7973 } else {
7974 for _ in 0..pad { wc!(b' '); }
7975 ws!(b"(null)".as_ptr(), slen);
7976 }
7977 } else {
7978 let full_len = strlen(s as *const c_char);
7979 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7980 let padded_len = if width > slen { width } else { slen };
7981 let pad = padded_len - slen;
7982 if flags & FLAG_MINUS != 0 {
7983 ws!(s as *const u8, slen);
7984 for _ in 0..pad { wc!(b' '); }
7985 } else {
7986 for _ in 0..pad { wc!(b' '); }
7987 ws!(s as *const u8, slen);
7988 }
7989 }
7990 }
7991 b'd' | b'i' => {
7992 let d = args.next_arg::<c_int>();
7993 let neg = d < 0;
7994 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7995 let b = format_u64(abs);
7996 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7997 let mut fbuf = [0u8; 32];
7998 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7999 ws_buf!(fbuf.as_ptr(), len);
8000 }
8001 b'u' => {
8002 let u = args.next_arg::<c_uint>();
8003 let b = format_u64(u as u64);
8004 let mut fbuf = [0u8; 32];
8005 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8006 ws_buf!(fbuf.as_ptr(), len);
8007 }
8008 b'x' => {
8009 let x = args.next_arg::<c_uint>();
8010 let b = format_hex(x as u64, false);
8011 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8012 let mut fbuf = [0u8; 32];
8013 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8014 ws_buf!(fbuf.as_ptr(), len);
8015 }
8016 b'X' => {
8017 let x = args.next_arg::<c_uint>();
8018 let b = format_hex(x as u64, true);
8019 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8020 let mut fbuf = [0u8; 32];
8021 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8022 ws_buf!(fbuf.as_ptr(), len);
8023 }
8024 b'o' => {
8025 let o = args.next_arg::<c_uint>();
8026 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8027 let mut fbuf = [0u8; 32];
8028 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8029 ws_buf!(fbuf.as_ptr(), len);
8030 }
8031 b'c' => {
8032 let ch = args.next_arg::<c_int>();
8033 if width > 1 {
8034 let pad = width - 1;
8035 if flags & FLAG_MINUS != 0 {
8036 wc!(ch as u8);
8037 for _ in 0..pad { wc!(b' '); }
8038 } else {
8039 for _ in 0..pad { wc!(b' '); }
8040 wc!(ch as u8);
8041 }
8042 } else {
8043 wc!(ch as u8);
8044 }
8045 }
8046 b'p' => {
8047 wc!(b'0'); wc!(b'x');
8048 let p = args.next_arg::<*const c_void>();
8049 let b = format_hex(p as u64, false);
8050 ws!(b.0.as_ptr(), b.1);
8051 }
8052 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8053 let val = args.next_arg::<f64>();
8054 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8055 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8056 let mut fbuf = [0u8; 4224];
8057 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8058 let mut wbuf = [0u8; 4224];
8059 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8060 ws_buf!(wbuf.as_ptr(), wlen);
8061 }
8062 b'%' => { wc!(b'%'); }
8063 b'n' => {
8064 let p = args.next_arg::<*mut c_void>();
8065 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8066 }
8067 _ => { wc!(b'%'); wc!(spec); }
8068 }
8069 }
8070 i += 1;
8071 }
8072 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8073 count as c_int
8074}
8075
8076#[no_mangle]
8077pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8078 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8079}
8080
8081#[no_mangle]
8082pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8083 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8084}
8085
8086#[no_mangle]
8087pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8088 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8089}
8090
8091#[no_mangle]
8092pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8093 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8094}
8095
8096unsafe fn skip_ws(p: *const u8) -> *const u8 {
8101 let mut q = p;
8102 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8103 q
8104}
8105
8106#[inline]
8107fn is_ws_byte(c: u8) -> bool {
8108 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8109}
8110
8111unsafe fn scan_int_val(
8114 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8115) -> (u64, bool, bool) {
8116 let start = *pos;
8117 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8118 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8119 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8120 else { false };
8121 if *pos >= max { *pos = start; return (0, false, false); }
8122 let mut base = base;
8123 let mut val: u64 = 0;
8124 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8126 *pos += 1;
8127 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8128 *pos += 1;
8129 if *pos < max {
8130 if let Some(d) = hex_val(*buf.add(*pos)) {
8131 val = d as u64; *pos += 1;
8132 while *pos < max { if let Some(d) = hex_val(*buf.add(*pos)) { val = val.wrapping_mul(16).wrapping_add(d as u64); *pos += 1; } else { break; } }
8133 return (val, neg, true);
8134 }
8135 }
8136 return (0, neg, false);
8137 } else if base == 0 {
8138 while *pos < max { let c = *buf.add(*pos); if c >= b'0' && c <= b'7' { val = val.wrapping_mul(8).wrapping_add((c - b'0') as u64); *pos += 1; } else { break; } }
8139 return (val, neg, true);
8140 } else {
8141 return (0, neg, true); }
8143 }
8144 if base == 0 { base = 10; }
8145 let mut found = false;
8146 while *pos < max {
8147 let c = *buf.add(*pos);
8148 let d: Option<u64> = match base {
8149 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8150 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8151 16 => hex_val(c).map(|v| v as u64),
8152 _ => None,
8153 };
8154 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8155 }
8156 if !found { *pos = start; return (0, false, false); }
8157 (val, neg, true)
8158}
8159
8160unsafe fn scan_float_val(
8162 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8163) -> (f64, bool) {
8164 let start = *pos;
8165 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8166 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8167 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8168 else { false };
8169 if *pos + 2 < max {
8171 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8172 if (c0==b'i'||c0==b'I')&&(c1==b'n'||c1==b'N')&&(c2==b'f'||c2==b'F') { *pos+=3; return (if neg{f64::NEG_INFINITY}else{f64::INFINITY}, true); }
8173 if (c0==b'n'||c0==b'N')&&(c1==b'a'||c1==b'A')&&(c2==b'n'||c2==b'N') { *pos+=3; return (if neg{-f64::NAN}else{f64::NAN}, true); }
8174 }
8175 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8177 *pos += 2;
8178 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8179 while *pos < max {
8180 if let Some(d) = hex_val(*buf.add(*pos)) {
8181 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8182 *pos += 1; found = true;
8183 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8184 }
8185 if !found { *pos = start; return (0.0, false); }
8186 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8188 *pos += 1;
8189 let mut eneg = false;
8190 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8191 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8192 let mut ev: i32 = 0; let mut ef = false;
8193 while *pos<max && *buf.add(*pos)>=b'0' && *buf.add(*pos)<=b'9' { ev = ev*10+(*buf.add(*pos)-b'0') as i32; *pos+=1; ef=true; }
8194 if !ef { return (0.0, false); }
8195 if eneg { ev = -ev; }
8196 val *= libm::pow(2.0, ev as f64);
8197 }
8198 return (if neg{-val}else{val}, true);
8199 }
8200 let token_start = start;
8201 let mut i = start;
8202 let mut saw_digit = false;
8203 let mut saw_dot = false;
8204 let mut saw_exp = false;
8205 let mut first = true;
8206 while i < max {
8207 let c = *buf.add(i);
8208 if (c == b'+' || c == b'-') && first {
8209 i += 1; first = false; continue;
8210 }
8211 if c >= b'0' && c <= b'9' {
8212 saw_digit = true; i += 1; first = false; continue;
8213 }
8214 if c == b'.' && !saw_dot && !saw_exp {
8215 saw_dot = true; i += 1; first = false; continue;
8216 }
8217 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8218 saw_exp = true; i += 1; first = true; continue;
8219 }
8220 break;
8221 }
8222 if !saw_digit { return (0.0, false); }
8223 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8224 match <f64 as core::str::FromStr>::from_str(s) {
8225 Ok(v) => { *pos = i; return (v, true); }
8226 Err(_) => { return (0.0, false); }
8227 }
8228}
8229
8230unsafe fn do_vsscanf(
8233 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8234) -> c_int {
8235 let mut p = 0usize;
8236 let mut fi = 0usize;
8237 let mut assigned = 0i32;
8238 let mut input_eof = false;
8239 loop {
8240 let fc = *fmt.add(fi) as u8;
8241 if fc == 0 { break; }
8242 if is_ws_byte(fc) {
8243 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8244 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8245 continue;
8246 }
8247 if fc != b'%' {
8248 if p >= buf_len { input_eof = true; break; }
8249 if *buf.add(p) != fc { break; }
8250 p += 1; fi += 1; continue;
8251 }
8252 fi += 1;
8253 if *fmt.add(fi) as u8 == b'%' {
8255 if p >= buf_len { input_eof = true; break; }
8256 if *buf.add(p) != b'%' { break; }
8257 p += 1; fi += 1; continue;
8258 }
8259 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8260 let mut width: usize = 0;
8261 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8262 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8263 }
8264 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8265 let mut len_mod = 0u8;
8266 match *fmt.add(fi) as u8 {
8267 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8268 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8269 b'j' => { fi += 1; len_mod = 4; }
8270 b'z' | b't' => { fi += 1; len_mod = 3; }
8271 b'L' => { fi += 1; len_mod = 5; }
8272 _ => {}
8273 }
8274 let spec = *fmt.add(fi) as u8;
8275 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8276 match real_spec {
8277 b'n' => {
8278 if !suppress { let out = args.next_arg::<*mut c_int>(); if !out.is_null() { *out = p as c_int; } }
8279 }
8280 b'd' | b'u' => {
8281 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8282 if p >= buf_len { input_eof = true; break; }
8283 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8284 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8285 if !ok { break; }
8286 if let Some(out) = dest { if !out.is_null() {
8287 *out = if real_spec==b'd' && neg { -(val as i64) as c_int } else { val as c_int };
8288 }}
8289 if !suppress { assigned += 1; }
8290 }
8291 b'i' => {
8292 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8293 if p >= buf_len { input_eof = true; break; }
8294 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8295 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8296 if !ok { break; }
8297 if let Some(out) = dest { if !out.is_null() { *out = if neg { -(val as i64) as c_int } else { val as c_int }; } }
8298 if !suppress { assigned += 1; }
8299 }
8300 b'o' => {
8301 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8302 if p >= buf_len { input_eof = true; break; }
8303 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8304 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8305 if !ok { break; }
8306 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8307 if !suppress { assigned += 1; }
8308 }
8309 b'x' | b'X' => {
8310 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8311 if p >= buf_len { input_eof = true; break; }
8312 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8313 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8314 if !ok { break; }
8315 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8316 if !suppress { assigned += 1; }
8317 }
8318 b'p' => {
8319 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8320 if p >= buf_len { input_eof = true; break; }
8321 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8322 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8323 if !ok { break; }
8324 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8325 if !suppress { assigned += 1; }
8326 }
8327 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8328 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8329 if p >= buf_len { input_eof = true; break; }
8330 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8331 if !ok { break; }
8332 if !suppress {
8333 if _real_len == 3 {
8334 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8335 } else if _real_len == 5 {
8336 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8337 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8338 #[cfg(target_arch = "x86_64")]
8339 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8340 } else {
8341 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8342 }
8343 }
8344 if !suppress { assigned += 1; }
8345 }
8346 b'c' => {
8347 let w = if width > 0 { width } else { 1 };
8348 if p >= buf_len { input_eof = true; break; }
8349 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8350 let start_p = p;
8351 let mut j = 0usize;
8352 while j < w && p < buf_len {
8353 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8354 p += 1; j += 1;
8355 }
8356 if j != w { p = start_p; input_eof = true; break; }
8357 if !suppress { assigned += 1; }
8358 }
8359 b's' => {
8360 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8361 if p >= buf_len { input_eof = true; break; }
8362 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8363 let w = if width > 0 { width } else { usize::MAX };
8364 let mut j = 0usize;
8365 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8366 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8367 p += 1; j += 1;
8368 }
8369 if j == 0 { break; }
8370 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8371 if !suppress { assigned += 1; }
8372 }
8373 b'[' => {
8374 fi += 1;
8375 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8376 let mut charset = [0u8; 256];
8377 if *fmt.add(fi) as u8 == b']' { charset[b']' as usize] = 1; fi += 1; }
8378 loop { let c = *fmt.add(fi) as u8; if c == b']' || c == 0 { break; } charset[c as usize] = 1; fi += 1; }
8379 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8380 fi -= 1; if p >= buf_len { input_eof = true; break; }
8382 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8383 let w = if width > 0 { width } else { usize::MAX };
8384 let mut j = 0usize;
8385 while p < buf_len && *buf.add(p) != 0 && j < w {
8386 let c = *buf.add(p);
8387 let in_set = charset[c as usize] != 0;
8388 if negate { if in_set { break; } } else { if !in_set { break; } }
8389 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8390 p += 1; j += 1;
8391 }
8392 if j == 0 { break; }
8393 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8394 if !suppress { assigned += 1; }
8395 }
8396 _ => break,
8397 }
8398 fi += 1;
8399 }
8400 if !consumed.is_null() { *consumed = p; }
8401 if assigned == 0 && input_eof { -1 } else { assigned }
8402}
8403
8404unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8405 let len = strlen(buf as *const c_char);
8406 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8407}
8408
8409#[no_mangle]
8410pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8411 vsscanf_inner(buf as *const u8, fmt, &mut args)
8412}
8413
8414#[no_mangle]
8415pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8416 let f = &mut *stream;
8417 let start_ungotten_count = f.ungotten_count as usize;
8418 let sfunc = f.seek_fn;
8419 let start_pos = sfunc.map(|s| s(stream, 0, SEEK_CUR)).unwrap_or(-1);
8420
8421 let mut line = [0u8; 4096];
8422 let mut pos = 0usize;
8423
8424 if start_pos >= 0 {
8425 while pos < line.len() - 1 {
8427 let c = fgetc(stream);
8428 if c == -1 { break; }
8429 line[pos] = c as u8;
8430 pos += 1;
8431 if c == b'\n' as c_int { break; }
8432 }
8433 } else {
8434 while f.ungotten_count > 0 && pos < line.len() - 1 {
8439 f.ungotten_count -= 1;
8440 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
8441 pos += 1;
8442 }
8443 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
8445 line[pos] = *f.rpos;
8446 f.rpos = f.rpos.add(1);
8447 pos += 1;
8448 }
8449 let fd = f.fd;
8451 let old_flags = sys_fcntl(fd, F_GETFL, 0);
8452 if old_flags >= 0 {
8453 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
8454 }
8455 while pos < line.len() - 1 {
8456 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
8457 if n <= 0 { break; }
8458 pos += n as usize;
8459 }
8460 if old_flags >= 0 {
8461 let _ = sys_fcntl(fd, F_SETFL, old_flags);
8462 }
8463 f._eof = 0;
8465 f._err = 0;
8466 f.flags &= !(F_EOF | F_ERR);
8467 }
8468
8469 line[pos] = 0;
8470 if pos == 0 { return 0; }
8471
8472 let mut consumed = 0usize;
8473 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
8474
8475 if start_pos >= 0 {
8476 let file_consumed = consumed.saturating_sub(start_ungotten_count);
8478 let target = start_pos + file_consumed as i64;
8479 if let Some(sfunc) = sfunc {
8480 sfunc(stream, target, SEEK_SET);
8481 }
8482 f.rpos = core::ptr::null_mut();
8483 f.rend = core::ptr::null_mut();
8484 if consumed < pos { f._eof = 0; }
8485 let remaining = start_ungotten_count.saturating_sub(consumed);
8486 f.ungotten_count = remaining as c_int;
8487 } else {
8488 let unconsumed = pos.saturating_sub(consumed);
8490 if unconsumed > 0 && !f.buf.is_null() {
8491 let copy_count = core::cmp::min(unconsumed, f.buf_size);
8492 core::ptr::copy(
8493 line.as_ptr().add(consumed),
8494 f.buf,
8495 copy_count,
8496 );
8497 f.rpos = f.buf;
8498 f.rend = f.buf.add(copy_count);
8499 }
8500 f.ungotten_count = 0;
8501 f._eof = 0;
8502 f.flags &= !F_EOF;
8503 }
8504 assigned
8505}
8506
8507#[no_mangle]
8508pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
8509 vfscanf(stdin, fmt, args)
8510}
8511
8512#[no_mangle]
8513pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
8514 vsscanf_inner(buf as *const u8, fmt, &mut args)
8515}
8516
8517#[no_mangle]
8518pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
8519 vfscanf(stream, fmt, args)
8520}
8521
8522#[no_mangle]
8523pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
8524 vfscanf(stdin, fmt, args)
8525}
8526
8527#[no_mangle]
8532pub unsafe extern "C" fn getdelim(
8533 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
8534) -> isize {
8535 if lineptr.is_null() || n.is_null() { return -1; }
8536 let mut cap = *n;
8537 let mut buf = *lineptr;
8538 if buf.is_null() || cap == 0 {
8539 cap = 128;
8540 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
8541 if buf.is_null() { return -1; }
8542 *lineptr = buf;
8543 *n = cap;
8544 }
8545 let mut len = 0usize;
8546 loop {
8547 let c = fgetc(stream);
8548 if c == -1 { if len == 0 { return -1; } break; }
8549 if len + 1 >= cap {
8550 let new_cap = cap.wrapping_mul(2);
8551 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
8552 if new_buf.is_null() { return -1; }
8553 buf = new_buf; cap = new_cap;
8554 *lineptr = buf; *n = cap;
8555 }
8556 *buf.add(len) = c as c_char;
8557 len += 1;
8558 if c == delim { break; }
8559 }
8560 *buf.add(len) = 0;
8561 len as isize
8562}
8563
8564#[no_mangle]
8565pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
8566 getdelim(lineptr, n, b'\n' as c_int, stream)
8567}
8568
8569#[no_mangle]
8574pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
8575 if cmd.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
8576 let m = *mode;
8577 if m != b'r' as c_char && m != b'w' as c_char { ERRNO = EINVAL; return core::ptr::null_mut(); }
8578 let mut p: [c_int; 2] = [0; 2];
8579 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
8580 let op = if m == b'r' as c_char { 0 } else { 1 };
8581 let child_fd = p[1 - op];
8582 let f = fdopen(p[op], mode);
8583 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
8584 let pid = sys_fork();
8585 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
8586 if pid == 0 {
8587 sys_close(p[op] as i64);
8588 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
8589 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
8590 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
8591 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
8592 _exit(127);
8593 }
8594 sys_close(child_fd as i64);
8595 (*f).pipe_pid = pid as c_int;
8596 f
8597}
8598
8599#[no_mangle]
8600pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
8601 let pid = (*f).pipe_pid;
8602 let r = fclose(f);
8603 if pid <= 0 { return -1; }
8604 let mut status: c_int = 0;
8605 let mut w: c_int;
8606 loop {
8607 w = waitpid(pid, &mut status, 0);
8608 if w >= 0 || w != -EINTR { break; }
8609 }
8610 if w < 0 || r != 0 { return -1; }
8611 status
8612}
8613
8614const L_TMPNAM: usize = 20;
8619static mut TMPNAM_COUNTER: c_uint = 0;
8620
8621unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
8622 let prefix = b"/tmp/tmp\0";
8623 let mut k = 0;
8624 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
8625 let (buf, len) = format_hex(seed as u64, false);
8626 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
8627 *out.add(k) = 0;
8628}
8629
8630#[no_mangle]
8631pub unsafe extern "C" fn tmpfile() -> *mut FILE {
8632 let mut name = [0u8; L_TMPNAM];
8633 let mut ctr: c_uint = 0;
8634 loop {
8635 ctr = ctr.wrapping_add(1);
8636 let mut ts: timespec = core::mem::zeroed();
8637 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8638 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
8639 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
8640 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
8641 if fd >= 0 {
8642 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
8643 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
8644 if f.is_null() { sys_close(fd); }
8645 return f;
8646 }
8647 if ctr > 100 { return core::ptr::null_mut(); }
8648 }
8649}
8650
8651#[no_mangle]
8652pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
8653 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
8654 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
8655 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
8656 let mut ts: timespec = core::mem::zeroed();
8657 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8658 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
8659 fill_tmpname(out, seed);
8660 out
8661}
8662
8663#[no_mangle]
8664pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
8665 if path.is_null() { ERRNO = EINVAL; return -1; }
8666 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
8667 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
8668}
8669
8670#[no_mangle]
8671pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
8672 if old.is_null() || new_.is_null() { ERRNO = EINVAL; return -1; }
8673 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
8674 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
8675}
8676
8677const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
8683const PAGE: usize = 4096;
8684
8685#[no_mangle]
8686pub unsafe extern "C" fn malloc(size: SizeT) -> *mut c_void {
8687 let alloc_size = if size == 0 { 1 } else { size };
8690 let total = alloc_size + core::mem::size_of::<usize>();
8692 let pages = (total + PAGE - 1) & !(PAGE - 1);
8693 let ptr = sys_mmap(
8694 null_mut(),
8695 pages,
8696 PROT_READ | PROT_WRITE,
8697 MAP_PRIVATE | MAP_ANONYMOUS,
8698 -1,
8699 0,
8700 );
8701 if ptr == MMAP_FAILED {
8702 return null_mut();
8703 }
8704 *(ptr as *mut usize) = pages;
8705 ptr.add(core::mem::size_of::<usize>()) as *mut c_void
8706}
8707
8708#[no_mangle]
8709pub unsafe extern "C" fn free(ptr: *mut c_void) {
8710 if ptr.is_null() {
8711 return;
8712 }
8713 let header = (ptr as *mut u8).sub(core::mem::size_of::<usize>());
8714 let pages = *(header as *const usize);
8715 sys_munmap(header, pages);
8716}
8717
8718#[no_mangle]
8719pub unsafe extern "C" fn calloc(count: SizeT, size: SizeT) -> *mut c_void {
8720 let total = count.saturating_mul(size);
8721 let ptr = malloc(total);
8722 if !ptr.is_null() {
8723 core::ptr::write_bytes(ptr as *mut u8, 0, total);
8724 }
8725 ptr
8726}
8727
8728#[no_mangle]
8729pub unsafe extern "C" fn realloc(ptr: *mut c_void, new_size: SizeT) -> *mut c_void {
8730 if ptr.is_null() {
8731 return malloc(new_size);
8732 }
8733 if new_size == 0 {
8734 free(ptr);
8735 return null_mut();
8736 }
8737 let header = (ptr as *mut u8).sub(core::mem::size_of::<usize>());
8738 let old_pages = *(header as *const usize);
8739 let old_data_size = old_pages - core::mem::size_of::<usize>();
8740 let new_ptr = malloc(new_size);
8741 if new_ptr.is_null() {
8742 return null_mut();
8743 }
8744 let copy_size = if old_data_size < new_size {
8745 old_data_size
8746 } else {
8747 new_size
8748 };
8749 core::ptr::copy_nonoverlapping(ptr as *const u8, new_ptr as *mut u8, copy_size);
8750 free(ptr);
8751 new_ptr
8752}
8753
8754#[no_mangle]
8759pub unsafe extern "C" fn _exit(code: c_int) -> ! {
8760 sys_exit_group(code)
8761}
8762
8763#[inline]
8764unsafe fn sys_exit_group(code: c_int) -> ! {
8765 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
8766}
8767
8768#[inline]
8769unsafe fn sys_exit_thread(code: c_int) -> ! {
8770 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
8771}
8772
8773#[no_mangle]
8774pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
8775 _exit(code);
8776}
8777
8778#[no_mangle]
8779pub unsafe extern "C" fn exit(code: c_int) -> ! {
8780 fflush(core::ptr::null_mut());
8781 __funcs_on_exit();
8782 _exit(code);
8783}
8784
8785#[no_mangle]
8786pub unsafe extern "C" fn abort() -> ! {
8787 raise(6); _exit(128 + 6);
8789}
8790
8791#[no_mangle]
8794pub static mut __stack_chk_guard: usize = 0;
8795
8796#[no_mangle]
8797pub unsafe extern "C" fn __stack_chk_fail() -> ! {
8798 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
8799 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
8800 abort();
8801}
8802
8803type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
8808
8809const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
8810const AR_MASK: usize = AR_LEN - 1;
8811
8812unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
8813 if p[0] != 1 {
8814 p[0].wrapping_sub(1).trailing_zeros() as i32
8815 } else if p[1] != 0 {
8816 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
8817 } else {
8818 0
8819 }
8820}
8821
8822unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
8823 if n < 2 { return; }
8824 let mut tmp = [0u8; 256];
8825 ar[n] = tmp.as_mut_ptr();
8826 let mut w = width;
8827 while w > 0 {
8828 let l = if 256 < w { 256 } else { w };
8829 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
8830 for i in 0..n {
8831 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
8832 ar[i] = ar[i].add(l);
8833 }
8834 w -= l;
8835 }
8836}
8837
8838unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
8839 let bits = (8 * core::mem::size_of::<usize>()) as i32;
8840 if n >= bits {
8841 p[1] = p[0];
8842 p[0] = 0;
8843 let n = n - bits;
8844 if n == 0 { return; }
8845 }
8846 p[1] = (p[1] << n) | (p[0] >> (bits - n));
8847 p[0] <<= n;
8848}
8849
8850unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
8851 let bits = (8 * core::mem::size_of::<usize>()) as i32;
8852 if n >= bits {
8853 p[0] = p[1];
8854 p[1] = 0;
8855 let n = n - bits;
8856 if n == 0 { return; }
8857 }
8858 p[0] = (p[0] >> n) | (p[1] << (bits - n));
8859 p[1] >>= n;
8860}
8861
8862unsafe fn qsort_sift(
8863 head: *mut u8, width: usize,
8864 cmp: CmpRfn, arg: *mut c_void,
8865 pshift: i32, lp: &[usize],
8866) {
8867 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
8868 ar[0] = head;
8869 let mut i = 1usize;
8870 let mut h = head;
8871 let mut ps = pshift;
8872
8873 while ps > 1 {
8874 let rt = h.sub(width);
8875 let lf = h.sub(width + lp[(ps - 2) as usize]);
8876
8877 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
8878 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
8879 {
8880 break;
8881 }
8882 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
8883 ar[i & AR_MASK] = lf;
8884 i += 1;
8885 h = lf;
8886 ps -= 1;
8887 } else {
8888 ar[i & AR_MASK] = rt;
8889 i += 1;
8890 h = rt;
8891 ps -= 2;
8892 }
8893 }
8894 qsort_cycle(width, &mut ar, i & AR_MASK);
8895}
8896
8897unsafe fn qsort_trinkle(
8898 head: *mut u8, width: usize,
8899 cmp: CmpRfn, arg: *mut c_void,
8900 pp: &[usize; 2], pshift: i32, trusty: i32,
8901 lp: &[usize],
8902) {
8903 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
8904 let mut p = *pp;
8905 ar[0] = head;
8906 let mut i = 1usize;
8907 let mut h = head;
8908 let mut ps = pshift;
8909 let mut t = trusty;
8910
8911 while p[0] != 1 || p[1] != 0 {
8912 let stepson = h.sub(lp[ps as usize]);
8913 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
8914 break;
8915 }
8916 if t == 0 && ps > 1 {
8917 let rt = h.sub(width);
8918 let lf = h.sub(width + lp[(ps - 2) as usize]);
8919 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
8920 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
8921 {
8922 break;
8923 }
8924 }
8925
8926 ar[i & AR_MASK] = stepson;
8927 i += 1;
8928 h = stepson;
8929 let trail = qsort_pntz(&p);
8930 qsort_shr(&mut p, trail);
8931 ps += trail;
8932 t = 0;
8933 }
8934 if t == 0 {
8935 qsort_cycle(width, &mut ar, i & AR_MASK);
8936 qsort_sift(h, width, cmp, arg, ps, lp);
8937 }
8938}
8939
8940#[no_mangle]
8941pub unsafe extern "C" fn __qsort_r(
8942 base: *mut c_void,
8943 nel: usize,
8944 width: usize,
8945 cmp: CmpRfn,
8946 arg: *mut c_void,
8947) {
8948 let size = width * nel;
8949 if size == 0 { return; }
8950
8951 let mut lp = [0usize; 96];
8952 lp[0] = width;
8953 lp[1] = width;
8954 let mut li = 2;
8955 while {
8956 lp[li] = lp[li - 2] + lp[li - 1] + width;
8957 lp[li] < size
8958 } {
8959 li += 1;
8960 }
8961
8962 let mut head = base as *mut u8;
8963 let high = head.add(size - width);
8964 let mut p: [usize; 2] = [1, 0];
8965 let mut pshift: i32 = 1;
8966
8967 while head < high {
8968 if (p[0] & 3) == 3 {
8969 qsort_sift(head, width, cmp, arg, pshift, &lp);
8970 qsort_shr(&mut p, 2);
8971 pshift += 2;
8972 } else {
8973 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
8974 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
8975 } else {
8976 qsort_sift(head, width, cmp, arg, pshift, &lp);
8977 }
8978
8979 if pshift == 1 {
8980 qsort_shl(&mut p, 1);
8981 pshift = 0;
8982 } else {
8983 qsort_shl(&mut p, pshift - 1);
8984 pshift = 1;
8985 }
8986 }
8987
8988 p[0] |= 1;
8989 head = head.add(width);
8990 }
8991
8992 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
8993
8994 while pshift != 1 || p[0] != 1 || p[1] != 0 {
8995 if pshift <= 1 {
8996 let trail = qsort_pntz(&p);
8997 qsort_shr(&mut p, trail);
8998 pshift += trail;
8999 } else {
9000 qsort_shl(&mut p, 2);
9001 pshift -= 2;
9002 p[0] ^= 7;
9003 qsort_shr(&mut p, 1);
9004 qsort_trinkle(
9005 head.sub(lp[pshift as usize] + width),
9006 width, cmp, arg, &p, pshift + 1, 1, &lp,
9007 );
9008 qsort_shl(&mut p, 1);
9009 p[0] |= 1;
9010 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9011 }
9012 head = head.sub(width);
9013 }
9014}
9015
9016#[no_mangle]
9017pub unsafe extern "C" fn qsort_r(
9018 base: *mut c_void,
9019 nel: usize,
9020 width: usize,
9021 cmp: CmpRfn,
9022 arg: *mut c_void,
9023) {
9024 __qsort_r(base, nel, width, cmp, arg);
9025}
9026
9027unsafe extern "C" fn qsort_wrap_cmp(
9028 a: *const c_void,
9029 b: *const c_void,
9030 cmp_ctx: *mut c_void,
9031) -> c_int {
9032 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9033 cmp(a, b)
9034}
9035
9036#[no_mangle]
9037pub unsafe extern "C" fn qsort(
9038 base: *mut c_void,
9039 nel: usize,
9040 width: usize,
9041 cmp: CmpFn,
9042) {
9043 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9044}
9045
9046const ATEXIT_COUNT: usize = 32;
9051
9052#[repr(C)]
9053struct AtExitBlock {
9054 next: *mut AtExitBlock,
9055 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9056 a: [*mut c_void; ATEXIT_COUNT],
9057}
9058
9059static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9060 next: core::ptr::null_mut(),
9061 f: [None; ATEXIT_COUNT],
9062 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9063};
9064static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9065static mut ATEXIT_SLOT: usize = 0;
9066static mut ATEXIT_FINISHED: bool = false;
9067
9068#[no_mangle]
9069pub unsafe extern "C" fn __funcs_on_exit() {
9070 while !ATEXIT_HEAD.is_null() {
9071 let head = ATEXIT_HEAD;
9072 while ATEXIT_SLOT > 0 {
9073 ATEXIT_SLOT -= 1;
9074 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9075 let a = (*head).a[ATEXIT_SLOT];
9076 f(a);
9077 }
9078 }
9079 ATEXIT_HEAD = (*head).next;
9080 ATEXIT_SLOT = ATEXIT_COUNT;
9081 }
9082 ATEXIT_FINISHED = true;
9083}
9084
9085#[no_mangle]
9086pub unsafe extern "C" fn __cxa_atexit(
9087 func: unsafe extern "C" fn(*mut c_void),
9088 arg: *mut c_void,
9089 _dso: *mut c_void,
9090) -> c_int {
9091 if ATEXIT_FINISHED {
9092 return -1;
9093 }
9094 if ATEXIT_HEAD.is_null() {
9095 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9096 }
9097 if ATEXIT_SLOT == ATEXIT_COUNT {
9098 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9099 if new.is_null() {
9100 return -1;
9101 }
9102 (*new).next = ATEXIT_HEAD;
9103 ATEXIT_HEAD = new;
9104 ATEXIT_SLOT = 0;
9105 }
9106 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9107 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9108 ATEXIT_SLOT += 1;
9109 0
9110}
9111
9112unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9113 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9114 func();
9115}
9116
9117#[no_mangle]
9118pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9119 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9120}
9121
9122#[no_mangle]
9123pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9124
9125#[no_mangle]
9130pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9131
9132const ENV_MAX_ALLOCED: usize = 256;
9134static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9135static mut ENV_ALLOCED_N: usize = 0;
9136
9137unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9138 for i in 0..ENV_ALLOCED_N {
9139 if ENV_ALLOCED[i] == old {
9140 ENV_ALLOCED[i] = new;
9141 if !old.is_null() {
9142 free(old as *mut c_void);
9143 }
9144 return;
9145 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9146 ENV_ALLOCED[i] = new;
9147 new = core::ptr::null_mut();
9148 }
9149 }
9150 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9151 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9152 ENV_ALLOCED_N += 1;
9153 }
9154}
9155
9156unsafe fn strchrnul(s: *const u8, c: u8) -> *const u8 {
9157 let mut p = s;
9158 while *p != 0 && *p != c {
9159 p = p.add(1);
9160 }
9161 p
9162}
9163
9164#[no_mangle]
9165pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9166 if __environ.is_null() || name.is_null() {
9167 return core::ptr::null_mut();
9168 }
9169 let name = name as *const u8;
9170 let l = strchrnul(name, b'=') as usize - name as usize;
9171 if l == 0 || *name.add(l) != 0 {
9172 return core::ptr::null_mut();
9173 }
9174 let mut e = __environ;
9175 while !(*e).is_null() {
9176 let entry = *e as *const u8;
9177 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9178 return entry.add(l + 1) as *mut c_char;
9179 }
9180 e = e.add(1);
9181 }
9182 core::ptr::null_mut()
9183}
9184
9185#[no_mangle]
9186pub unsafe extern "C" fn setenv(
9187 var: *const c_char,
9188 value: *const c_char,
9189 overwrite: c_int,
9190) -> c_int {
9191 if var.is_null() || value.is_null() {
9192 ERRNO = EINVAL;
9193 return -1;
9194 }
9195 let var = var as *const u8;
9196 let l1 = strchrnul(var, b'=') as usize - var as usize;
9197 if l1 == 0 || *var.add(l1) != 0 {
9198 ERRNO = EINVAL;
9199 return -1;
9200 }
9201 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9202 return 0;
9203 }
9204 let l2 = strlen(value as *const c_char);
9205 let s = malloc(l1 + l2 + 2) as *mut u8;
9206 if s.is_null() {
9207 return -1;
9208 }
9209 core::ptr::copy_nonoverlapping(var, s, l1);
9210 *s.add(l1) = b'=';
9211 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9212 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9213}
9214
9215unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9216 let mut i = 0;
9217 if !__environ.is_null() {
9218 let mut e = __environ;
9219 while !(*e).is_null() {
9220 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9221 let tmp = *e;
9222 *e = s;
9223 env_rm_add(tmp, r);
9224 return 0;
9225 }
9226 e = e.add(1);
9227 i += 1;
9228 }
9229 }
9230 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9231 if newenv.is_null() {
9232 if !r.is_null() { free(r as *mut c_void); }
9233 return -1;
9234 }
9235 if i > 0 && !__environ.is_null() {
9236 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9237 }
9238 *newenv.add(i) = s;
9239 *newenv.add(i + 1) = core::ptr::null_mut();
9240 __environ = newenv;
9242 environ = __environ;
9243 if !r.is_null() {
9244 env_rm_add(core::ptr::null_mut(), r);
9245 }
9246 0
9247}
9248
9249#[no_mangle]
9250pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9251 if s.is_null() { return -1; }
9252 let l = strchrnul(s as *const u8, b'=') as usize - s as *const u8 as usize;
9253 if l == 0 || *s.add(l) as u8 == 0 {
9254 return unsetenv(s);
9255 }
9256 putenv_internal(s, l, core::ptr::null_mut())
9257}
9258
9259#[no_mangle]
9260pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9261 if name.is_null() {
9262 ERRNO = EINVAL;
9263 return -1;
9264 }
9265 let name = name as *const u8;
9266 let l = strchrnul(name, b'=') as usize - name as usize;
9267 if l == 0 || *name.add(l) != 0 {
9268 ERRNO = EINVAL;
9269 return -1;
9270 }
9271 if __environ.is_null() {
9272 return 0;
9273 }
9274 let mut e = __environ;
9275 let mut eo = e;
9276 while !(*e).is_null() {
9277 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9278 env_rm_add(*e, core::ptr::null_mut());
9279 } else {
9280 if eo != e {
9281 *eo = *e;
9282 }
9283 eo = eo.add(1);
9284 }
9285 e = e.add(1);
9286 }
9287 if eo != e {
9288 *eo = core::ptr::null_mut();
9289 }
9290 environ = __environ;
9291 0
9292}
9293
9294#[no_mangle]
9295pub unsafe extern "C" fn clearenv() -> c_int {
9296 let e = __environ;
9297 __environ = core::ptr::null_mut();
9298 environ = core::ptr::null_mut();
9299 if !e.is_null() {
9300 let mut p = e;
9301 while !(*p).is_null() {
9302 env_rm_add(*p, core::ptr::null_mut());
9303 p = p.add(1);
9304 }
9305 }
9306 0
9307}
9308
9309static mut RANDOM_INIT: [u32; 32] = [
9315 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9316 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9317 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9318 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9319 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9320 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9321 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9322 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9323];
9324
9325static mut RANDOM_N: i32 = 31;
9326static mut RANDOM_I: i32 = 3;
9327static mut RANDOM_J: i32 = 0;
9328static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9329
9330unsafe fn random_lcg31(x: u32) -> u32 {
9331 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9332}
9333
9334unsafe fn random_lcg64(x: u64) -> u64 {
9335 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9336}
9337
9338unsafe fn random_savestate() -> *mut u8 {
9339 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9340 RANDOM_X.offset(-1) as *mut u8
9341}
9342
9343unsafe fn random_loadstate(state: *mut u32) {
9344 RANDOM_X = state.add(1);
9345 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9346 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9347 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9348}
9349
9350unsafe fn random_srandom_inner(seed: u32) {
9351 let mut s = seed as u64;
9352 if RANDOM_N == 0 {
9353 *RANDOM_X = s as u32;
9354 return;
9355 }
9356 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9357 RANDOM_J = 0;
9358 for k in 0..RANDOM_N as usize {
9359 s = random_lcg64(s);
9360 *RANDOM_X.add(k) = (s >> 32) as u32;
9361 }
9362 *RANDOM_X |= 1;
9363}
9364
9365#[no_mangle]
9366pub unsafe extern "C" fn srandom(seed: c_uint) {
9367 random_srandom_inner(seed);
9368}
9369
9370#[no_mangle]
9371pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9372 if size < 8 { return core::ptr::null_mut(); }
9373 let old = random_savestate();
9374 RANDOM_N = if size < 32 { 0 }
9375 else if size < 64 { 7 }
9376 else if size < 128 { 15 }
9377 else if size < 256 { 31 }
9378 else { 63 };
9379 RANDOM_X = (state as *mut u32).add(1);
9380 random_srandom_inner(seed);
9381 random_savestate();
9382 old as *mut c_char
9383}
9384
9385#[no_mangle]
9386pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9387 let old = random_savestate();
9388 random_loadstate(state as *mut u32);
9389 old as *mut c_char
9390}
9391
9392#[no_mangle]
9393pub unsafe extern "C" fn random() -> c_long {
9394 let k: c_long;
9395 if RANDOM_N == 0 {
9396 *RANDOM_X = random_lcg31(*RANDOM_X);
9397 k = *RANDOM_X as c_long;
9398 } else {
9399 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9400 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9401 RANDOM_I += 1;
9402 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9403 RANDOM_J += 1;
9404 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9405 }
9406 k
9407}
9408
9409const SA: u8 = 0xC2;
9414const SB: u8 = 0xF4;
9415
9416const BITTAB: [u32; 51] = [
9417 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9418 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9419 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9420 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9421 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9422 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9423 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9424 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9425 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9426];
9427
9428#[inline]
9429fn mb_oob(c: u32, b: u8) -> u32 {
9430 let b3 = (b >> 3) as u32;
9431 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9432}
9433
9434static mut MB_STATE: c_uint = 0;
9435
9436const MB_CUR_MAX_VAL_UTF8: usize = 4;
9437const MB_CUR_MAX_VAL_C: usize = 1;
9438
9439#[no_mangle]
9440pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9441 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9442}
9443
9444#[no_mangle]
9445pub unsafe extern "C" fn mbrtowc(
9446 wc: *mut c_int,
9447 src: *const c_char,
9448 n: usize,
9449 st: *mut c_uint,
9450) -> usize {
9451 let s = src as *const u8;
9452 let n0 = n;
9453 let mut dummy: c_int = 0;
9454 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9455 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9456
9457 let mut c: u32 = *st;
9458 let mut s = s;
9459 let mut n = n;
9460
9461 if s.is_null() {
9462 if c != 0 { *st = 0; ERRNO = EILSEQ; return !0usize; }
9463 return 0;
9464 }
9465
9466 if n == 0 { return !1usize; }
9467
9468 if unsafe { !LOCALE_CTYPE_UTF8 } {
9469 let b = *s;
9470 *wc = b as c_int;
9471 return if b == 0 { 0 } else { 1 };
9472 }
9473
9474 if c == 0 {
9475 if *s < 0x80 {
9476 let r = if *s == 0 { 0 } else { 1 };
9477 *wc = *s as c_int;
9478 return r;
9479 }
9480 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
9481 *st = 0; ERRNO = EILSEQ; return !0usize;
9482 }
9483 c = BITTAB[*s as usize - SA as usize];
9484 s = s.add(1);
9485 n -= 1;
9486 }
9487
9488 if n > 0 {
9489 if mb_oob(c, *s) != 0 {
9490 *st = 0; ERRNO = EILSEQ; return !0usize;
9491 }
9492 loop {
9493 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
9494 s = s.add(1);
9495 n -= 1;
9496 if c & (1u32 << 31) == 0 {
9497 *st = 0;
9498 *wc = c as c_int;
9499 return n0 - n;
9500 }
9501 if n == 0 { break; }
9502 if (*s).wrapping_sub(0x80) >= 0x40 {
9503 *st = 0; ERRNO = EILSEQ; return !0usize;
9504 }
9505 }
9506 }
9507
9508 *st = c;
9509 !1usize
9510}
9511
9512#[no_mangle]
9513pub unsafe extern "C" fn wcrtomb(
9514 s: *mut c_char,
9515 wc: c_int,
9516 _st: *mut c_uint,
9517) -> usize {
9518 if s.is_null() { return 1; }
9519 let wc_u = wc as u32;
9520 if unsafe { !LOCALE_CTYPE_UTF8 } {
9521 if wc_u > 0xFF {
9522 ERRNO = EILSEQ;
9523 return !0usize;
9524 }
9525 *s = wc as c_char;
9526 return 1;
9527 }
9528 if wc_u < 0x80 {
9529 *s = wc as c_char;
9530 return 1;
9531 }
9532 if wc_u < 0x800 {
9533 *s = (0xC0 | (wc_u >> 6)) as c_char;
9534 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
9535 return 2;
9536 }
9537 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
9538 *s = (0xE0 | (wc_u >> 12)) as c_char;
9539 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9540 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
9541 return 3;
9542 }
9543 if wc_u.wrapping_sub(0x10000) < 0x100000 {
9544 *s = (0xF0 | (wc_u >> 18)) as c_char;
9545 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
9546 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9547 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
9548 return 4;
9549 }
9550 ERRNO = EILSEQ;
9551 !0usize
9552}
9553
9554#[no_mangle]
9555pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
9556 if s.is_null() { return 0; }
9557 mbtowc(core::ptr::null_mut(), s, n)
9558}
9559
9560#[no_mangle]
9561pub unsafe extern "C" fn mbtowc(
9562 wc: *mut c_int,
9563 src: *const c_char,
9564 n: usize,
9565) -> c_int {
9566 if src.is_null() { return 0; }
9567 if n == 0 { ERRNO = EILSEQ; return -1; }
9568 let mut state: c_uint = 0;
9569 let mut w: c_int = 0;
9570 let r = mbrtowc(&mut w, src, n, &mut state);
9571 if r == !0usize { return -1; }
9572 if !wc.is_null() { *wc = w; }
9573 r as c_int
9574}
9575
9576#[no_mangle]
9577pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
9578 if s.is_null() { return 0; }
9579 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
9580}
9581
9582#[no_mangle]
9583pub unsafe extern "C" fn mbsrtowcs(
9584 ws: *mut c_int,
9585 src: *mut *const c_char,
9586 wn: usize,
9587 st: *mut c_uint,
9588) -> usize {
9589 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9590 let mut s = *src as *const u8;
9591 let wn0 = wn;
9592 let mut wn = wn;
9593
9594 if ws.is_null() {
9595 while *s != 0 {
9596 if *s < 0x80 {
9597 s = s.add(1);
9598 wn = wn.wrapping_sub(1);
9599 continue;
9600 }
9601 let mut wc: c_int = 0;
9602 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9603 if r == !0usize { return !0usize; }
9604 if r == !1usize { return wn0 - wn; }
9605 s = s.add(r);
9606 wn = wn.wrapping_sub(1);
9607 }
9608 wn0 - wn
9609 } else {
9610 let mut w = ws;
9611 while wn > 0 {
9612 if *s < 0x80 {
9613 let c = *s as c_int;
9614 *w = c;
9615 if c == 0 {
9616 *src = core::ptr::null();
9617 return wn0 - wn;
9618 }
9619 w = w.add(1);
9620 s = s.add(1);
9621 wn -= 1;
9622 continue;
9623 }
9624 let mut wc: c_int = 0;
9625 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9626 if r == !0usize {
9627 *src = s as *const c_char;
9628 return !0usize;
9629 }
9630 if r == !1usize {
9631 *src = s as *const c_char;
9632 return wn0 - wn;
9633 }
9634 *w = wc;
9635 w = w.add(1);
9636 s = s.add(r);
9637 wn -= 1;
9638 }
9639 *src = s as *const c_char;
9640 wn0 - wn
9641 }
9642}
9643
9644#[no_mangle]
9645pub unsafe extern "C" fn wcsrtombs(
9646 s: *mut c_char,
9647 ws: *mut *const c_int,
9648 n: usize,
9649 _st: *mut c_uint,
9650) -> usize {
9651 let mut w = *ws;
9652 let n0 = n;
9653 let mut n = n;
9654
9655 if s.is_null() {
9656 let mut count = 0usize;
9657 while *w != 0 {
9658 if (*w as u32) < 0x80 {
9659 count += 1;
9660 } else {
9661 let mut buf = [0u8; 4];
9662 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
9663 if r == !0usize { return !0usize; }
9664 count += r;
9665 }
9666 w = w.add(1);
9667 }
9668 return count;
9669 }
9670
9671 let mut dst = s;
9672 while n > 0 {
9673 if (*w as u32) < 0x80 {
9674 *dst = *w as c_char;
9675 if *w == 0 {
9676 *ws = core::ptr::null();
9677 return n0 - n;
9678 }
9679 dst = dst.add(1);
9680 n -= 1;
9681 } else {
9682 let r = wcrtomb(dst, *w, core::ptr::null_mut());
9683 if r == !0usize {
9684 *ws = w;
9685 return !0usize;
9686 }
9687 if r > n {
9688 *ws = w;
9689 return n0 - n;
9690 }
9691 dst = dst.add(r);
9692 n -= r;
9693 }
9694 w = w.add(1);
9695 }
9696 *ws = w;
9697 n0
9698}
9699
9700#[no_mangle]
9701pub unsafe extern "C" fn mbstowcs(
9702 ws: *mut c_int,
9703 src: *const c_char,
9704 wn: usize,
9705) -> usize {
9706 let mut src_ptr = src;
9707 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
9708}
9709
9710#[no_mangle]
9711pub unsafe extern "C" fn wcstombs(
9712 s: *mut c_char,
9713 ws: *const c_int,
9714 n: usize,
9715) -> usize {
9716 let mut ws_ptr = ws;
9717 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
9718}
9719
9720#[no_mangle]
9725pub extern "C" fn btowc(c: c_int) -> wint_t {
9726 if c == -1 { return WEOF; }
9727 unsafe {
9728 if LOCALE_CTYPE_UTF8 {
9729 if (c as u32) < 128 { c as wint_t } else { WEOF }
9730 } else {
9731 (c as u8) as wint_t
9732 }
9733 }
9734}
9735
9736#[no_mangle]
9737pub extern "C" fn wctob(c: wint_t) -> c_int {
9738 unsafe {
9739 if LOCALE_CTYPE_UTF8 {
9740 if c < 128 { c as c_int } else { -1 }
9741 } else {
9742 if c <= 0xFF { c as c_int } else { -1 }
9743 }
9744 }
9745}
9746
9747#[no_mangle]
9748pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
9749 if s.is_null() || *s == 0 { 1 } else { 0 }
9750}
9751
9752#[no_mangle]
9753pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
9754 mbrtowc(core::ptr::null_mut(), s, n, ps)
9755}
9756
9757#[no_mangle]
9762pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
9763 let mut len = 0;
9764 while *s.add(len) != 0 { len += 1; }
9765 len
9766}
9767
9768#[no_mangle]
9769pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
9770 let mut i = 0;
9771 loop {
9772 let ch = *s.add(i);
9773 if ch == c { return s.add(i) as *mut wchar_t; }
9774 if ch == 0 { return null_mut(); }
9775 i += 1;
9776 }
9777}
9778
9779#[no_mangle]
9780pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
9781 let mut i = 0;
9782 let mut last: *mut wchar_t = null_mut();
9783 loop {
9784 let ch = *s.add(i);
9785 if ch == c { last = s.add(i) as *mut wchar_t; }
9786 if ch == 0 { return last; }
9787 i += 1;
9788 }
9789}
9790
9791#[no_mangle]
9792pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
9793 if *needle == 0 { return haystack as *mut wchar_t; }
9794 let mut i = 0;
9795 loop {
9796 let h = *haystack.add(i);
9797 if h == 0 { return null_mut(); }
9798 if h == *needle {
9799 let mut j = 0;
9800 loop {
9801 let n = *needle.add(j);
9802 if n == 0 { return haystack.add(i) as *mut wchar_t; }
9803 if *haystack.add(i + j) != n { break; }
9804 j += 1;
9805 }
9806 }
9807 i += 1;
9808 }
9809}
9810
9811#[no_mangle]
9812pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
9813 let mut i = 0;
9814 loop {
9815 let a = *s1.add(i);
9816 let b = *s2.add(i);
9817 if a != b { return a - b; }
9818 if a == 0 { return 0; }
9819 i += 1;
9820 }
9821}
9822
9823#[no_mangle]
9824pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
9825 let mut i = 0;
9826 while i < n {
9827 let a = *s1.add(i);
9828 let b = *s2.add(i);
9829 if a != b { return a - b; }
9830 if a == 0 { return 0; }
9831 i += 1;
9832 }
9833 0
9834}
9835
9836#[no_mangle]
9837pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
9838 let mut i = 0;
9839 loop {
9840 let c = *src.add(i);
9841 *dst.add(i) = c;
9842 if c == 0 { break; }
9843 i += 1;
9844 }
9845 dst
9846}
9847
9848#[no_mangle]
9849pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
9850 let mut i = 0;
9851 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
9852 while i < n { *dst.add(i) = 0; i += 1; }
9853 dst
9854}
9855
9856#[no_mangle]
9857pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
9858 let mut i = 0;
9859 while *dst.add(i) != 0 { i += 1; }
9860 let mut j = 0;
9861 loop {
9862 let c = *src.add(j);
9863 *dst.add(i + j) = c;
9864 if c == 0 { break; }
9865 j += 1;
9866 }
9867 dst
9868}
9869
9870#[no_mangle]
9871pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
9872 let mut i = 0;
9873 while *dst.add(i) != 0 { i += 1; }
9874 let mut j = 0;
9875 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
9876 *dst.add(i + j) = 0;
9877 dst
9878}
9879
9880#[no_mangle]
9881pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
9882 let len = wcslen(s);
9883 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
9884 if p.is_null() { return null_mut(); }
9885 core::ptr::copy_nonoverlapping(s, p, len + 1);
9886 p
9887}
9888
9889#[no_mangle]
9890pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
9891 let mut i = 0;
9892 while i < maxlen && *s.add(i) != 0 { i += 1; }
9893 i
9894}
9895
9896#[no_mangle]
9897pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
9898 let mut i = 0;
9899 loop {
9900 let c = *s.add(i);
9901 if c == 0 { return i; }
9902 let mut found = false;
9903 let mut j = 0;
9904 loop {
9905 let a = *accept.add(j);
9906 if a == 0 { break; }
9907 if c == a { found = true; break; }
9908 j += 1;
9909 }
9910 if !found { return i; }
9911 i += 1;
9912 }
9913}
9914
9915#[no_mangle]
9916pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
9917 let mut i = 0;
9918 loop {
9919 let c = *s.add(i);
9920 if c == 0 { return i; }
9921 let mut j = 0;
9922 loop {
9923 let r = *reject.add(j);
9924 if r == 0 { break; }
9925 if c == r { return i; }
9926 j += 1;
9927 }
9928 i += 1;
9929 }
9930}
9931
9932#[no_mangle]
9933pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
9934 let mut i = 0;
9935 loop {
9936 let c = *s.add(i);
9937 if c == 0 { return null_mut(); }
9938 let mut j = 0;
9939 loop {
9940 let a = *accept.add(j);
9941 if a == 0 { break; }
9942 if c == a { return s.add(i) as *mut wchar_t; }
9943 j += 1;
9944 }
9945 i += 1;
9946 }
9947}
9948
9949#[no_mangle]
9950pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
9951 let len = wcslen(src);
9952 if !dst.is_null() {
9953 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
9954 for i in 0..copy { *dst.add(i) = *src.add(i); }
9955 if n > 0 { *dst.add(copy) = 0; }
9956 }
9957 len
9958}
9959
9960unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
9965 let mut i = 0;
9966 while i < bufsz - 1 {
9967 let c = *ws.add(i);
9968 if c == 0 { break; }
9969 if (c as u32) > 127 { break; }
9970 *buf.add(i) = c as u8;
9971 i += 1;
9972 }
9973 *buf.add(i) = 0;
9974 i
9975}
9976
9977#[no_mangle]
9978pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
9979 let mut buf = [0u8; 256];
9980 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9981 let mut end: *mut c_char = core::ptr::null_mut();
9982 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
9983 if !endptr.is_null() {
9984 let offset = end as usize - buf.as_ptr() as usize;
9985 *endptr = s.add(offset) as *mut wchar_t;
9986 }
9987 r
9988}
9989
9990#[no_mangle]
9991pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
9992 let mut buf = [0u8; 256];
9993 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9994 let mut end: *mut c_char = core::ptr::null_mut();
9995 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
9996 if !endptr.is_null() {
9997 let offset = end as usize - buf.as_ptr() as usize;
9998 *endptr = s.add(offset) as *mut wchar_t;
9999 }
10000 r
10001}
10002
10003#[no_mangle]
10004pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10005 let mut buf = [0u8; 256];
10006 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10007 let mut end: *mut c_char = core::ptr::null_mut();
10008 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10009 if !endptr.is_null() {
10010 let offset = end as usize - buf.as_ptr() as usize;
10011 *endptr = s.add(offset) as *mut wchar_t;
10012 }
10013 r
10014}
10015
10016#[no_mangle]
10017pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10018 let mut buf = [0u8; 256];
10019 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10020 let mut end: *mut c_char = core::ptr::null_mut();
10021 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10022 if !endptr.is_null() {
10023 let offset = end as usize - buf.as_ptr() as usize;
10024 *endptr = s.add(offset) as *mut wchar_t;
10025 }
10026 r
10027}
10028
10029#[no_mangle]
10030pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10031 let mut buf = [0u8; 256];
10032 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10033 let mut end: *mut c_char = core::ptr::null_mut();
10034 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10035 if !endptr.is_null() {
10036 let offset = end as usize - buf.as_ptr() as usize;
10037 *endptr = s.add(offset) as *mut wchar_t;
10038 }
10039 r
10040}
10041
10042#[no_mangle]
10043pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10044
10045#[no_mangle]
10046#[cfg(target_arch = "x86_64")]
10047pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10048
10049#[no_mangle]
10050#[cfg(target_arch = "aarch64")]
10051pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10052
10053#[no_mangle]
10054#[cfg(target_arch = "riscv64")]
10055pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10056
10057#[no_mangle]
10058pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10059
10060#[no_mangle]
10061pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10062
10063const WC_ALPHA: c_int = 1;
10068const WC_DIGIT: c_int = 2;
10069const WC_SPACE: c_int = 4;
10070const WC_UPPER: c_int = 8;
10071const WC_LOWER: c_int = 16;
10072const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10073const WC_BLANK: c_int = 32;
10074const WC_CNTRL: c_int = 64;
10075const WC_PUNCT: c_int = 128;
10076const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10077const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10078const WC_XDIGIT: c_int = 256;
10079
10080fn wc_flags(c: wint_t) -> c_int {
10081 if c < 128 {
10082 let f = CT_TABLE[c as usize];
10083 let mut r = 0;
10084 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10085 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10086 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10087 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10088 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10089 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10090 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10091 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10092 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10093 r
10094 } else {
10095 if c < 0x100 { 0 }
10096 else { WC_PRINT | WC_ALPHA }
10097 }
10098}
10099
10100#[no_mangle]
10101pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10102#[no_mangle]
10103pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10104#[no_mangle]
10105pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10106#[no_mangle]
10107pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10108#[no_mangle]
10109pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10110#[no_mangle]
10111pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10112#[no_mangle]
10113pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10114#[no_mangle]
10115pub extern "C" fn iswprint(c: wint_t) -> c_int {
10116 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10117 else if c >= 0x100 && c < 0x110000 { 1 }
10118 else { 0 }
10119}
10120#[no_mangle]
10121pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10122#[no_mangle]
10123pub extern "C" fn iswspace(c: wint_t) -> c_int {
10124 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10125 else {
10126 match c {
10127 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10128 _ => 0,
10129 }
10130 }
10131}
10132#[no_mangle]
10133pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10134#[no_mangle]
10135pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10136
10137static WCTYPE_ALNUM: c_int = WC_ALNUM;
10138static WCTYPE_ALPHA: c_int = WC_ALPHA;
10139static WCTYPE_BLANK: c_int = WC_BLANK;
10140static WCTYPE_CNTRL: c_int = WC_CNTRL;
10141static WCTYPE_DIGIT: c_int = WC_DIGIT;
10142static WCTYPE_GRAPH: c_int = WC_GRAPH;
10143static WCTYPE_LOWER: c_int = WC_LOWER;
10144static WCTYPE_PRINT: c_int = WC_PRINT;
10145static WCTYPE_PUNCT: c_int = WC_PUNCT;
10146static WCTYPE_SPACE: c_int = WC_SPACE;
10147static WCTYPE_UPPER: c_int = WC_UPPER;
10148static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10149
10150#[no_mangle]
10151pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10152 if name.is_null() { return core::ptr::null(); }
10153 let n = name as *const u8;
10154 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10155 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10156 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10157 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10158 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10159 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10160 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10161 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10162 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10163 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10164 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10165 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10166 core::ptr::null()
10167}
10168
10169#[no_mangle]
10170pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10171 if desc.is_null() { return 0; }
10172 (wc_flags(c) & *desc != 0) as c_int
10173}
10174
10175static WCTRANS_LOWER: c_int = 1;
10176static WCTRANS_UPPER: c_int = 2;
10177
10178#[no_mangle]
10179pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10180 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10181}
10182
10183#[no_mangle]
10184pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10185 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10186}
10187
10188#[no_mangle]
10189pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10190 if name.is_null() { return core::ptr::null(); }
10191 let n = name as *const u8;
10192 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10193 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10194 core::ptr::null()
10195}
10196
10197#[no_mangle]
10198pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10199 if desc.is_null() { return c; }
10200 match *desc {
10201 1 => towlower(c),
10202 2 => towupper(c),
10203 _ => c,
10204 }
10205}
10206
10207#[no_mangle]
10212pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10213 let mut state: c_uint = 0;
10214 let mut wc: wchar_t = 0;
10215 let mut buf = [0u8; 4];
10216 let c = fgetc(f);
10217 if c == -1 { return WEOF; }
10218 buf[0] = c as u8;
10219 if buf[0] < 0x80 { return buf[0] as wint_t; }
10220 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10221 let mut n = 1usize;
10222 while n < len {
10223 let c2 = fgetc(f);
10224 if c2 == -1 { return WEOF; }
10225 buf[n] = c2 as u8;
10226 n += 1;
10227 }
10228 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10229 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10230}
10231
10232#[no_mangle]
10233pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10234 let mut buf = [0u8; 4];
10235 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10236 if n == !0usize || n == 0 { return WEOF; }
10237 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10238 c as wint_t
10239}
10240
10241#[no_mangle]
10242pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10243 let mut i = 0;
10244 while *s.add(i) != 0 {
10245 if fputwc(*s.add(i), f) == WEOF { return -1; }
10246 i += 1;
10247 }
10248 0
10249}
10250
10251#[no_mangle]
10252pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10253 if c == WEOF { return WEOF; }
10254 let mut buf = [0u8; 4];
10255 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10256 if n == !0usize || n == 0 { return WEOF; }
10257 let mut i = n;
10258 while i > 0 {
10259 i -= 1;
10260 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10261 }
10262 c
10263}
10264
10265#[no_mangle]
10266pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10267
10268#[no_mangle]
10269pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10270
10271unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10276 let mut i = 0;
10277 while i < len {
10278 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10279 i += 1;
10280 }
10281 pos + len
10282}
10283
10284#[no_mangle]
10285pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10286 if n == 0 { return -1; }
10287 let cap = n - 1;
10288 let mut pos = 0usize;
10289 let mut fmt_narrow = [0u8; 256];
10291 let mut flen = 0usize;
10292 loop {
10293 let ch = *fmt.add(flen) as u32;
10294 if ch == 0 || flen >= 255 { break; }
10295 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10296 flen += 1;
10297 }
10298 fmt_narrow[flen] = 0;
10299 let mut fi = 0usize;
10300 macro_rules! wc {
10301 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10302 }
10303 loop {
10304 let c = fmt_narrow[fi];
10305 if c == 0 { break; }
10306 if c != b'%' { wc!(c); fi += 1; continue; }
10307 fi += 1;
10308 let mut flags: u8 = 0;
10309 loop {
10310 match fmt_narrow[fi] {
10311 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10312 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10313 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10314 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10315 b'#' => { flags |= FLAG_HASH; fi += 1; }
10316 _ => break,
10317 }
10318 }
10319 let mut width: usize = 0;
10320 if fmt_narrow[fi] == b'*' {
10321 let w = args.next_arg::<c_int>();
10322 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10323 fi += 1;
10324 } else {
10325 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10326 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10327 }
10328 }
10329 let mut precision: i32 = -1;
10330 if fmt_narrow[fi] == b'.' {
10331 fi += 1;
10332 if fmt_narrow[fi] == b'*' {
10333 let p = args.next_arg::<c_int>();
10334 precision = if p < 0 { -1 } else { p }; fi += 1;
10335 } else {
10336 precision = 0;
10337 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10338 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10339 }
10340 }
10341 }
10342 let len_mod = fmt_narrow[fi];
10343 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
10344 fi += 1;
10345 let spec = fmt_narrow[fi];
10346 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10347 fi += 1;
10348 let spec2 = fmt_narrow[fi];
10349 match (len_mod, spec, spec2) {
10350 (b'h', b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u8) = pos as u8; } }
10351 (b'l', b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_longlong) = pos as c_longlong; } }
10352 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10353 let val = args.next_arg::<c_longlong>();
10354 let neg = val < 0;
10355 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10356 let b = format_u64(abs);
10357 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10358 let mut fbuf = [0u8; 32];
10359 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10360 for k in 0..len { wc!(fbuf[k]); }
10361 }
10362 (b'l', b'l', b'u') => {
10363 let val = args.next_arg::<c_ulonglong>();
10364 let b = format_u64(val as u64);
10365 let mut fbuf = [0u8; 32];
10366 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10367 for k in 0..len { wc!(fbuf[k]); }
10368 }
10369 (b'l', b'l', b'x') => {
10370 let val = args.next_arg::<c_ulonglong>();
10371 let b = format_hex(val as u64, false);
10372 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10373 let mut fbuf = [0u8; 32];
10374 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10375 for k in 0..len { wc!(fbuf[k]); }
10376 }
10377 (b'l', b'l', b'X') => {
10378 let val = args.next_arg::<c_ulonglong>();
10379 let b = format_hex(val as u64, true);
10380 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10381 let mut fbuf = [0u8; 32];
10382 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10383 for k in 0..len { wc!(fbuf[k]); }
10384 }
10385 (b'l', b'l', b'o') => {
10386 let val = args.next_arg::<c_ulonglong>();
10387 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10388 let mut fbuf = [0u8; 32];
10389 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10390 for k in 0..len { wc!(fbuf[k]); }
10391 }
10392 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10393 }
10394 } else {
10395 match (len_mod, spec) {
10396 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10397 (b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_long) = pos as c_long; } }
10398 (b'z', b'n') | (b't', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut usize) = pos; } }
10399 (b'j', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_ulonglong) = pos as c_ulonglong; } }
10400 (b'l', b'd') | (b'l', b'i') => {
10401 let val = args.next_arg::<c_long>();
10402 let neg = val < 0;
10403 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10404 let b = format_u64(abs);
10405 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10406 let mut fbuf = [0u8; 32];
10407 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10408 for k in 0..len { wc!(fbuf[k]); }
10409 }
10410 (b'l', b'u') => {
10411 let val = args.next_arg::<c_ulong>();
10412 let b = format_u64(val as u64);
10413 let mut fbuf = [0u8; 32];
10414 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10415 for k in 0..len { wc!(fbuf[k]); }
10416 }
10417 (b'l', b'x') => {
10418 let val = args.next_arg::<c_ulong>();
10419 let b = format_hex(val as u64, false);
10420 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10421 let mut fbuf = [0u8; 32];
10422 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10423 for k in 0..len { wc!(fbuf[k]); }
10424 }
10425 (b'l', b'X') => {
10426 let val = args.next_arg::<c_ulong>();
10427 let b = format_hex(val as u64, true);
10428 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10429 let mut fbuf = [0u8; 32];
10430 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10431 for k in 0..len { wc!(fbuf[k]); }
10432 }
10433 (b'l', b'o') => {
10434 let val = args.next_arg::<c_ulong>();
10435 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10436 let mut fbuf = [0u8; 32];
10437 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10438 for k in 0..len { wc!(fbuf[k]); }
10439 }
10440 (b'l', b'c') => {
10441 let ch = args.next_arg::<wint_t>();
10442 wc!(ch);
10443 }
10444 (b'l', b's') => {
10445 let ws_arg = args.next_arg::<*const wchar_t>();
10446 if ws_arg.is_null() {
10447 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10448 if flags & FLAG_MINUS != 0 {
10449 for k in 0..slen { wc!(b"(null)"[k]); }
10450 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10451 } else {
10452 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10453 for k in 0..slen { wc!(b"(null)"[k]); }
10454 }
10455 } else {
10456 let mut wlen = 0usize;
10457 loop {
10458 let ch = *ws_arg.add(wlen);
10459 if ch == 0 { break; }
10460 if precision >= 0 && wlen >= precision as usize { break; }
10461 wlen += 1;
10462 }
10463 if flags & FLAG_MINUS != 0 {
10464 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10465 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10466 } else {
10467 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10468 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10469 }
10470 }
10471 }
10472 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
10473 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
10474 let val = args.next_arg::<f64>();
10475 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10476 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10477 let mut fbuf = [0u8; 4224];
10478 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10479 let mut wbuf = [0u8; 4224];
10480 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10481 for k in 0..wlen { wc!(wbuf[k]); }
10482 }
10483 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
10484 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
10485 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
10486 let val = {
10487 let lo: u64 = args.next_arg::<u64>();
10488 let hi: u64 = args.next_arg::<u64>();
10489 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
10490 f128::from_bits(combined) as f64
10491 };
10492 #[cfg(target_arch = "x86_64")]
10493 let val = args.next_arg::<f64>();
10494 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10495 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10496 let mut fbuf = [0u8; 4224];
10497 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10498 let mut wbuf = [0u8; 4224];
10499 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10500 for k in 0..wlen { wc!(wbuf[k]); }
10501 }
10502 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
10503 }
10504 }
10505 } else {
10506 let spec = fmt_narrow[fi];
10507 match spec {
10508 b'd' | b'i' => {
10509 let d = args.next_arg::<c_int>();
10510 let neg = d < 0;
10511 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
10512 let b = format_u64(abs);
10513 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10514 let mut fbuf = [0u8; 32];
10515 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10516 for k in 0..len { wc!(fbuf[k]); }
10517 }
10518 b'u' => {
10519 let u = args.next_arg::<c_uint>();
10520 let b = format_u64(u as u64);
10521 let mut fbuf = [0u8; 32];
10522 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10523 for k in 0..len { wc!(fbuf[k]); }
10524 }
10525 b'x' => {
10526 let x = args.next_arg::<c_uint>();
10527 let b = format_hex(x as u64, false);
10528 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10529 let mut fbuf = [0u8; 32];
10530 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10531 for k in 0..len { wc!(fbuf[k]); }
10532 }
10533 b'X' => {
10534 let x = args.next_arg::<c_uint>();
10535 let b = format_hex(x as u64, true);
10536 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10537 let mut fbuf = [0u8; 32];
10538 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10539 for k in 0..len { wc!(fbuf[k]); }
10540 }
10541 b'o' => {
10542 let o = args.next_arg::<c_uint>();
10543 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
10544 let mut fbuf = [0u8; 32];
10545 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10546 for k in 0..len { wc!(fbuf[k]); }
10547 }
10548 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
10549 let val = args.next_arg::<f64>();
10550 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10551 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10552 let mut fbuf = [0u8; 4224];
10553 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10554 let mut wbuf = [0u8; 4224];
10555 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10556 for k in 0..wlen { wc!(wbuf[k]); }
10557 }
10558 b'c' => {
10559 let ch = args.next_arg::<c_int>();
10560 wc!(ch as u8);
10561 }
10562 b's' => {
10563 let p = args.next_arg::<*const c_char>();
10564 if p.is_null() {
10565 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10566 if flags & FLAG_MINUS != 0 {
10567 for k in 0..slen { wc!(b"(null)"[k]); }
10568 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10569 } else {
10570 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10571 for k in 0..slen { wc!(b"(null)"[k]); }
10572 }
10573 } else {
10574 let mut wbuf_local = [0i32; 256];
10575 let mut wcount = 0usize;
10576 let mut byte_pos = 0usize;
10577 let pbytes = p as *const u8;
10578 loop {
10579 if precision >= 0 && wcount >= precision as usize { break; }
10580 if wcount >= 256 { break; }
10581 let mut wc_val: c_int = 0;
10582 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
10583 if consumed == !0usize || consumed == !1usize {
10584 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
10585 byte_pos += 1;
10586 wcount += 1;
10587 } else if consumed == 0 {
10588 break;
10589 } else {
10590 wbuf_local[wcount] = wc_val;
10591 byte_pos += consumed;
10592 wcount += 1;
10593 }
10594 }
10595 if flags & FLAG_MINUS != 0 {
10596 for k in 0..wcount { wc!(wbuf_local[k]); }
10597 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10598 } else {
10599 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10600 for k in 0..wcount { wc!(wbuf_local[k]); }
10601 }
10602 }
10603 }
10604 b'p' => {
10605 wc!(b'0'); wc!(b'x');
10606 let p = args.next_arg::<*const c_void>();
10607 let b = format_hex(p as u64, false);
10608 for k in 0..b.1 { wc!(b.0[k]); }
10609 }
10610 b'n' => {
10611 let p = args.next_arg::<*mut c_void>();
10612 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
10613 }
10614 b'%' => { wc!(b'%'); }
10615 _ => { wc!(b'%'); wc!(spec); }
10616 }
10617 }
10618 fi += 1;
10619 }
10620 let null_pos = if pos < cap { pos } else { cap };
10621 *s.add(null_pos) = 0;
10622 if pos > cap { -1 } else { pos as c_int }
10623}
10624
10625#[no_mangle]
10626pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
10627 vswprintf(s, n, fmt, args)
10628}
10629
10630#[no_mangle]
10631pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
10632 let mut buf = [0i32; 4096];
10633 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
10634 if r < 0 { return r; }
10635 let mut i = 0;
10636 while i < r as usize {
10637 let mut mb = [0u8; 4];
10638 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
10639 if n == !0usize { return -1; }
10640 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
10641 i += 1;
10642 }
10643 r
10644}
10645
10646#[no_mangle]
10647pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10648 vfwprintf(f, fmt, args)
10649}
10650
10651unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
10657 let mut i = 0usize;
10658 loop {
10659 let ch = *src.add(i) as u32;
10660 if ch == 0 || i >= dst_len - 1 { break; }
10661 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
10662 i += 1;
10663 }
10664 *dst.add(i) = 0;
10665}
10666
10667#[no_mangle]
10668pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
10669 let mut mbs_buf = [0u8; 4096];
10670 let mut i = 0usize;
10671 let mut mb_pos = 0usize;
10672 loop {
10673 let wc = *s.add(i) as c_int;
10674 if wc == 0 { break; }
10675 let mut mb = [0u8; 4];
10676 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
10677 if n == !0usize || n == 0 { break; }
10678 if mb_pos + n >= mbs_buf.len() { break; }
10679 let mut k = 0usize;
10680 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
10681 mb_pos += n;
10682 i += 1;
10683 }
10684 mbs_buf[mb_pos] = 0;
10685 let mut mbs_fmt = [0u8; 4096];
10686 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10687 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
10688}
10689
10690#[no_mangle]
10691pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
10692 vswscanf(s, fmt, args)
10693}
10694
10695#[no_mangle]
10696pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
10697 let start_pos = ftello(f);
10698 if start_pos < 0 { return -1; }
10699 let mut buf = [0u8; 4096];
10700 let mut n = 0usize;
10701 loop {
10702 if n >= buf.len() - 1 { break; }
10703 let c = fgetc(f);
10704 if c == -1 { break; }
10705 buf[n] = c as u8;
10706 n += 1;
10707 }
10708 buf[n] = 0;
10709 let mut mbs_fmt = [0u8; 4096];
10710 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10711 let mut consumed = 0usize;
10712 let hit_eof = (*f)._eof != 0;
10713 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
10714 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
10715 if hit_eof && consumed == n {
10716 (*f)._eof = 1;
10717 }
10718 result
10719}
10720
10721#[no_mangle]
10722pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10723 vfwscanf(f, fmt, args)
10724}
10725
10726#[no_mangle]
10727pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
10728 vfwscanf(stdin, fmt, args)
10729}
10730
10731#[no_mangle]
10732pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
10733 vfwscanf(stdin, fmt, args)
10734}
10735
10736const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
10741const DAYS_PER_400Y: i64 = 365 * 400 + 97;
10742const DAYS_PER_100Y: i64 = 365 * 100 + 24;
10743const DAYS_PER_4Y: i64 = 365 * 4 + 1;
10744
10745const SECS_THROUGH_MONTH: [i32; 12] = [
10746 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
10747 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
10748];
10749
10750const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
10751
10752unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
10753 if year - 2 <= 136 {
10754 let y = year as i32;
10755 let mut leaps = (y - 68) >> 2;
10756 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
10757 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
10758 }
10759 let mut cycles = ((year - 100) / 400) as i32;
10760 let mut rem = ((year - 100) % 400) as i32;
10761 if rem < 0 { cycles -= 1; rem += 400; }
10762 let (centuries, leaps);
10763 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
10764 else {
10765 let c;
10766 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
10767 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
10768 centuries = c;
10769 if rem == 0 { *is_leap = false; leaps = 0; }
10770 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
10771 }
10772 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
10773 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
10774}
10775
10776fn month_to_secs(month: i32, is_leap: bool) -> i32 {
10777 let mut t = SECS_THROUGH_MONTH[month as usize];
10778 if is_leap && month >= 2 { t += 86400; }
10779 t
10780}
10781
10782unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
10783 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
10784 let secs = t - LEAPOCH;
10785 let mut days = secs / 86400;
10786 let mut remsecs = (secs % 86400) as i32;
10787 if remsecs < 0 { remsecs += 86400; days -= 1; }
10788 let mut wday = ((3 + days) % 7) as i32;
10789 if wday < 0 { wday += 7; }
10790 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
10791 let mut remdays = (days % DAYS_PER_400Y) as i32;
10792 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
10793 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
10794 if c_cycles == 4 { c_cycles -= 1; }
10795 remdays -= c_cycles * DAYS_PER_100Y as i32;
10796 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
10797 if q_cycles == 25 { q_cycles -= 1; }
10798 remdays -= q_cycles * DAYS_PER_4Y as i32;
10799 let mut remyears = remdays / 365;
10800 if remyears == 4 { remyears -= 1; }
10801 remdays -= remyears * 365;
10802 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
10803 let mut yday = remdays + 31 + 28 + leap as i32;
10804 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
10805 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
10806 let mut months = 0i32;
10807 let mut rd = remdays;
10808 for m in 0..12 {
10809 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
10810 }
10811 let mut adj_years = years;
10812 if months >= 10 { months -= 12; adj_years += 1; }
10813 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
10814 tm.tm_year = (adj_years + 100) as c_int;
10815 tm.tm_mon = months + 2;
10816 tm.tm_mday = rd + 1;
10817 tm.tm_wday = wday;
10818 tm.tm_yday = yday;
10819 tm.tm_hour = remsecs / 3600;
10820 tm.tm_min = remsecs / 60 % 60;
10821 tm.tm_sec = remsecs % 60;
10822 true
10823}
10824
10825unsafe fn tm_to_secs(tm: *const tm) -> i64 {
10826 let mut year = (*tm).tm_year as i64;
10827 let mut month = (*tm).tm_mon;
10828 if month >= 12 || month < 0 {
10829 let adj = month / 12;
10830 month %= 12;
10831 if month < 0 { month += 12; }
10832 year += adj as i64;
10833 }
10834 let mut is_leap = false;
10835 let mut t = year_to_secs(year, &mut is_leap);
10836 t += month_to_secs(month, is_leap) as i64;
10837 t += 86400 * ((*tm).tm_mday - 1) as i64;
10838 t += 3600 * (*tm).tm_hour as i64;
10839 t += 60 * (*tm).tm_min as i64;
10840 t += (*tm).tm_sec as i64;
10841 t
10842}
10843
10844static mut TM_BUF: tm = tm {
10845 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
10846 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
10847 tm_gmtoff: 0, tm_zone: core::ptr::null(),
10848};
10849
10850static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
10851
10852const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
10853
10854#[no_mangle]
10859pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
10860 let mut ts: timespec = core::mem::zeroed();
10861 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
10862 if !t.is_null() { *t = ts.tv_sec; }
10863 ts.tv_sec
10864}
10865
10866#[no_mangle]
10867pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
10868 (t1 as i64 - t0 as i64) as f64
10869}
10870
10871#[no_mangle]
10872pub unsafe extern "C" fn clock() -> ClockT {
10873 let mut ts: timespec = core::mem::zeroed();
10874 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
10875 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
10876}
10877
10878#[no_mangle]
10879pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
10880 gmtime_r(t, &raw mut TM_BUF)
10881}
10882
10883#[no_mangle]
10884pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
10885 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO = EOVERFLOW; return core::ptr::null_mut(); }
10886 (*tm).tm_isdst = 0;
10887 (*tm).tm_gmtoff = 0;
10888 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10889 tm
10890}
10891
10892#[no_mangle]
10893pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
10894
10895#[no_mangle]
10896pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
10897
10898#[no_mangle]
10899pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
10900 let t = tm_to_secs(tm as *const tm);
10901 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
10902 (*tm).tm_isdst = 0;
10903 (*tm).tm_gmtoff = 0;
10904 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10905 t as TimeT
10906}
10907
10908#[no_mangle]
10909pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
10910 let t = tm_to_secs(tm as *const tm);
10911 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
10912 (*tm).tm_isdst = 0;
10913 (*tm).tm_gmtoff = 0;
10914 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10915 t as TimeT
10916}
10917
10918static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
10919
10920const DAY_NAMES: [&[u8]; 7] = [b"Sun\0", b"Mon\0", b"Tue\0", b"Wed\0", b"Thu\0", b"Fri\0", b"Sat\0"];
10921const MON_NAMES: [&[u8]; 12] = [b"Jan\0", b"Feb\0", b"Mar\0", b"Apr\0", b"May\0", b"Jun\0", b"Jul\0", b"Aug\0", b"Sep\0", b"Oct\0", b"Nov\0", b"Dec\0"];
10922
10923#[no_mangle]
10924pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
10925 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
10926}
10927
10928#[no_mangle]
10929pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
10930 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
10931 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
10932 let dn = DAY_NAMES[wday];
10933 let mn = MON_NAMES[mon];
10934 let mut p = 0;
10935 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
10936 *buf.add(p) = b' ' as c_char; p += 1;
10937 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
10938 *buf.add(p) = b' ' as c_char; p += 1;
10939 let v = (*tm).tm_mday;
10940 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
10941 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
10942 *buf.add(p) = b' ' as c_char; p += 1;
10943 let hh = (*tm).tm_hour;
10944 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
10945 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
10946 *buf.add(p) = b':' as c_char; p += 1;
10947 let mm = (*tm).tm_min;
10948 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
10949 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
10950 *buf.add(p) = b':' as c_char; p += 1;
10951 let ss = (*tm).tm_sec;
10952 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
10953 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
10954 *buf.add(p) = b' ' as c_char; p += 1;
10955 let yr = (*tm).tm_year + 1900;
10956 let mut tmp = [0u8; 4];
10957 let mut v2 = yr;
10958 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
10959 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
10960 *buf.add(p) = b'\n' as c_char; p += 1;
10961 *buf.add(p) = 0;
10962 buf
10963}
10964
10965#[no_mangle]
10966pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
10967
10968#[no_mangle]
10969pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
10970 let mut tmp: tm = core::mem::zeroed();
10971 gmtime_r(t, &mut tmp);
10972 asctime_r(&tmp, buf)
10973}
10974
10975unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
10980 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
10981}
10982
10983unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
10984 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
10985}
10986
10987unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
10988 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
10989}
10990
10991#[no_mangle]
10992pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int { if sys_clock_getres(clockid, ts) < 0 { -1 } else { 0 } }
10993
10994#[no_mangle]
10995pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int { if sys_clock_settime(clockid, ts) < 0 { -1 } else { 0 } }
10996
10997#[no_mangle]
10998pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
10999 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11000 if r < 0 { (-r) as c_int } else { 0 }
11001}
11002
11003#[no_mangle]
11004pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11005 if tv.is_null() { return 0; }
11006 let mut ts: timespec = core::mem::zeroed();
11007 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11008 (*tv).tv_sec = ts.tv_sec;
11009 (*tv).tv_usec = ts.tv_nsec / 1000;
11010 0
11011}
11012
11013fn is_leap_year(y: i32) -> bool {
11018 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11019 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11020}
11021
11022fn week_num(tm: &tm) -> i32 {
11023 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11024 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11025 if val == 0 {
11026 val = 52;
11027 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11028 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11029 } else if val == 53 {
11030 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11031 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11032 }
11033 val
11034}
11035
11036const ABDAY_1: c_int = 0x20000;
11038const DAY_1: c_int = 0x20007;
11039const ABMON_1: c_int = 0x2000E;
11040const MON_1: c_int = 0x2001A;
11041const AM_STR_LI: c_int = 0x20026;
11042const PM_STR_LI: c_int = 0x20027;
11043const D_T_FMT: c_int = 0x20028;
11044const D_FMT: c_int = 0x20029;
11045const T_FMT: c_int = 0x2002A;
11046const T_FMT_AMPM: c_int = 0x2002B;
11047
11048unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11051 let negative = val < 0;
11052 let mut v = if negative { -val as u64 } else { val as u64 };
11053 let mut tmp = [0u8; 24];
11054 let mut pos = 24usize;
11055 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11056 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11057 let digits = 24 - pos;
11058 let sign_chars = if negative { 1 } else { 0 };
11059 let needed = sign_chars + digits;
11060 let fill = if width > needed { width - needed } else { 0 };
11061 let total = fill + needed;
11062 let mut p = 0usize;
11063 match pad {
11064 b'-' => { }
11065 b'_' => {
11066 for _ in 0..fill { buf[p] = b' '; p += 1; }
11067 if negative { buf[p] = b'-'; p += 1; }
11068 }
11069 _ => {
11070 if negative { buf[p] = b'-'; p += 1; }
11071 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11072 }
11073 }
11074 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11075 (buf.as_ptr(), total)
11076}
11077
11078unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11080 let mut k = 0usize;
11081 while *s.add(k) != 0 {
11082 buf[k] = *s.add(k) as u8;
11083 k += 1;
11084 }
11085 (buf.as_ptr(), k)
11086}
11087
11088unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11091 let mut val: i64;
11092 let mut width: usize = 2;
11093 let mut def_pad: u8 = b'0';
11094 let fmt: *const c_char;
11095
11096 match f {
11097 b'a' => {
11098 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11099 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11100 return str_to_buf(buf, p);
11101 }
11102 b'A' => {
11103 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11104 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11105 return str_to_buf(buf, p);
11106 }
11107 b'h' | b'b' => {
11108 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11109 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11110 return str_to_buf(buf, p);
11111 }
11112 b'B' => {
11113 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11114 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11115 return str_to_buf(buf, p);
11116 }
11117 b'c' => {
11118 let p = nl_langinfo(D_T_FMT);
11119 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11120 return (buf.as_ptr(), l);
11121 }
11122 b'C' => {
11123 val = (1900i64 + (*tm).tm_year as i64) / 100;
11124 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11125 }
11126 b'e' => { def_pad = b'_'; }
11127 b'd' => {
11128 val = (*tm).tm_mday as i64;
11129 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11130 }
11131 b'D' => {
11132 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11133 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11134 return (buf.as_ptr(), l);
11135 }
11136 b'F' => {
11137 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11138 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11139 return (buf.as_ptr(), l);
11140 }
11141 b'g' | b'G' => {
11142 val = (*tm).tm_year as i64 + 1900;
11143 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11144 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11145 if f == b'g' { val %= 100; }
11146 else { width = 4; }
11147 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11148 }
11149 b'H' => {
11150 val = (*tm).tm_hour as i64;
11151 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11152 }
11153 b'I' => {
11154 val = (*tm).tm_hour as i64;
11155 if val == 0 { val = 12; }
11156 else if val > 12 { val -= 12; }
11157 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11158 }
11159 b'j' => {
11160 val = (*tm).tm_yday as i64 + 1;
11161 width = 3;
11162 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11163 }
11164 b'm' => {
11165 val = (*tm).tm_mon as i64 + 1;
11166 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11167 }
11168 b'M' => {
11169 val = (*tm).tm_min as i64;
11170 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11171 }
11172 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11173 b'p' => {
11174 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11175 return str_to_buf(buf, p);
11176 }
11177 b'r' => {
11178 let p = nl_langinfo(T_FMT_AMPM);
11179 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11180 return (buf.as_ptr(), l);
11181 }
11182 b'R' => {
11183 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11184 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11185 return (buf.as_ptr(), l);
11186 }
11187 b's' => {
11188 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11189 width = 1;
11190 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11191 }
11192 b'S' => {
11193 val = (*tm).tm_sec as i64;
11194 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11195 }
11196 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11197 b'T' => {
11198 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11199 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11200 return (buf.as_ptr(), l);
11201 }
11202 b'u' => {
11203 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11204 width = 1;
11205 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11206 }
11207 b'U' => {
11208 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11209 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11210 }
11211 b'W' => {
11212 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11213 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11214 }
11215 b'V' => {
11216 val = week_num(&*tm) as i64;
11217 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11218 }
11219 b'w' => {
11220 val = (*tm).tm_wday as i64;
11221 width = 1;
11222 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11223 }
11224 b'x' => {
11225 let p = nl_langinfo(D_FMT);
11226 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11227 return (buf.as_ptr(), l);
11228 }
11229 b'X' => {
11230 let p = nl_langinfo(T_FMT);
11231 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11232 return (buf.as_ptr(), l);
11233 }
11234 b'y' => {
11235 val = (1900i64 + (*tm).tm_year as i64) % 100;
11236 if val < 0 { val = -val; }
11237 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11238 }
11239 b'Y' => {
11240 val = (*tm).tm_year as i64 + 1900;
11241 if val >= 10000 {
11242 let mut tmp = [0u8; 100];
11243 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11244 buf[0] = b'+';
11245 for i in 0..k { buf[1 + i] = tmp[i]; }
11246 return (buf.as_ptr(), 1 + k);
11247 }
11248 width = 4;
11249 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11250 }
11251 b'z' => {
11252 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11253 let gmtoff = (*tm).tm_gmtoff as i64;
11254 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11255 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11256 let hh = (off / 3600) as i32;
11257 let mm = ((off % 3600) / 60) as i32;
11258 buf[0] = sign;
11259 buf[1] = b'0' + (hh / 10) as u8;
11260 buf[2] = b'0' + (hh % 10) as u8;
11261 buf[3] = b'0' + (mm / 10) as u8;
11262 buf[4] = b'0' + (mm % 10) as u8;
11263 return (buf.as_ptr(), 5);
11264 }
11265 b'Z' => {
11266 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11267 return str_to_buf(buf, (*tm).tm_zone);
11268 }
11269 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11270 _ => { return (core::ptr::null(), 0); }
11271 }
11272 val = (*tm).tm_mday as i64;
11274 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11275}
11276
11277unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11278 let mut l: usize = 0;
11279 let mut fi: usize = 0;
11280 while l < n {
11281 let ch = *f.add(fi) as u8;
11282 if ch == 0 {
11283 *s.add(l) = 0;
11284 return l;
11285 }
11286 if ch != b'%' {
11287 *s.add(l) = ch as c_char;
11288 l += 1;
11289 fi += 1;
11290 continue;
11291 }
11292 fi += 1;
11293 let mut pad: u8 = 0;
11295 let fc = *f.add(fi) as u8;
11296 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11297 let plus = *f.add(fi) as u8 == b'+';
11298 if plus { fi += 1; }
11299 let mut width: usize = 0;
11301 let mut p_idx = fi;
11302 {
11303 let fc2 = *f.add(fi) as u8;
11304 if fc2 >= b'0' && fc2 <= b'9' {
11305 let mut w: usize = 0;
11306 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11307 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11308 p_idx += 1;
11309 }
11310 width = w;
11311 }
11312 }
11313 let spec_ch = *f.add(p_idx) as u8;
11314 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11315 if width == 0 && p_idx != fi { width = 1; }
11316 } else {
11317 width = 0;
11318 }
11319 fi = p_idx;
11320 let fc3 = *f.add(fi) as u8;
11322 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11323 let fch = *f.add(fi) as u8;
11324 let mut buf = [0u8; 100];
11326 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11327 if t.is_null() { break; }
11328 let mut k = k;
11329 let mut t = t;
11330 if width != 0 {
11331 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11333 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11334 t = t.add(1); k -= 1;
11335 }
11336 if width < k { width = k; }
11337 let mut d: usize = 0;
11338 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11339 if (*tm).tm_year < -1900 {
11340 if l < n { *s.add(l) = b'-' as c_char; }
11341 l += 1;
11342 width -= 1;
11343 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11344 if l < n { *s.add(l) = b'+' as c_char; }
11345 l += 1;
11346 width -= 1;
11347 }
11348 while width > k && l < n {
11349 *s.add(l) = b'0' as c_char;
11350 l += 1;
11351 width -= 1;
11352 }
11353 }
11354 let copy = if k > n - l { n - l } else { k };
11355 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11356 l += copy;
11357 fi += 1;
11358 }
11359 if n > 0 {
11360 if l == n { l = n - 1; }
11361 *s.add(l) = 0;
11362 }
11363 0
11364}
11365
11366#[no_mangle]
11367pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11368 __strftime_l(s, maxsize, fmt, tm)
11369}
11370
11371unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11376 for i in 0..prefix.len() {
11377 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11378 }
11379 true
11380}
11381
11382unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11383 for i in 0..prefix.len() {
11384 let c = *s.add(i);
11385 if c == 0 { return false; }
11386 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11387 }
11388 true
11389}
11390
11391unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11392 let mut val = 0i32;
11393 let mut np = p;
11394 let mut count = 0;
11395 while *np >= b'0' && *np <= b'9' && count < max_digits {
11396 val = val * 10 + (*np - b'0') as i32;
11397 np = np.add(1);
11398 count += 1;
11399 }
11400 if count == 0 { (0, p) } else { (val, np) }
11401}
11402
11403unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11404 let (val, np) = parse_int(p, 4);
11405 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11406}
11407
11408fn is_ascii_space(c: u8) -> bool {
11409 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11410}
11411
11412#[no_mangle]
11413pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11414 let mut p = s as *const u8;
11415 let mut f = fmt as *const u8;
11416 let mut want_century = 0i32;
11417 let mut century = 0i32;
11418 let mut relyear = 0i32;
11419 while *f != 0 {
11420 if *f != b'%' {
11421 if is_ascii_space(*f) {
11422 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11423 } else {
11424 if *p != *f { return core::ptr::null_mut(); }
11425 p = p.add(1);
11426 }
11427 f = f.add(1);
11428 continue;
11429 }
11430 f = f.add(1);
11431 if *f == b'+' { f = f.add(1); }
11432 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11433 if *f == b'E' || *f == b'O' { f = f.add(1); }
11434 match *f {
11435 b'a' | b'A' => {
11436 let mut found = false;
11437 for i in 0..7 {
11438 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11439 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11440 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11441 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11442 }
11443 if !found { return core::ptr::null_mut(); }
11444 }
11445 b'b' | b'B' | b'h' => {
11446 let mut found = false;
11447 for i in 0..12 {
11448 let names: [&[u8]; 12] = [b"January", b"February", b"March", b"April", b"May", b"June", b"July", b"August", b"September", b"October", b"November", b"December"];
11449 let snames: [&[u8]; 12] = [b"Jan", b"Feb", b"Mar", b"Apr", b"May", b"Jun", b"Jul", b"Aug", b"Sep", b"Oct", b"Nov", b"Dec"];
11450 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11451 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11452 }
11453 if !found { return core::ptr::null_mut(); }
11454 }
11455 b'C' => {
11456 let (v, np) = parse_int(p, 2);
11457 if np == p { return core::ptr::null_mut(); }
11458 century = v;
11459 want_century |= 2;
11460 p = np;
11461 }
11462 b'd' | b'e' => {
11463 let (v, np) = parse_range(p, 1, 31);
11464 if np == p { return core::ptr::null_mut(); }
11465 (*tm).tm_mday = v;
11466 p = np;
11467 }
11468 b'D' => {
11469 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
11470 if r.is_null() { return core::ptr::null_mut(); }
11471 p = r as *const u8;
11472 }
11473 b'F' => {
11474 let (yv, ynp) = parse_int(p, 4);
11475 if ynp == p { return core::ptr::null_mut(); }
11476 (*tm).tm_year = yv - 1900;
11477 p = ynp;
11478 if *p != b'-' { return core::ptr::null_mut(); }
11479 p = p.add(1);
11480 let (mv, mnp) = parse_range(p, 1, 12);
11481 if mnp == p { return core::ptr::null_mut(); }
11482 (*tm).tm_mon = mv - 1;
11483 p = mnp;
11484 if *p != b'-' { return core::ptr::null_mut(); }
11485 p = p.add(1);
11486 let (dv, dnp) = parse_range(p, 1, 31);
11487 if dnp == p { return core::ptr::null_mut(); }
11488 (*tm).tm_mday = dv;
11489 p = dnp;
11490 }
11491 b'H' | b'I' => {
11492 let (v, np) = parse_range(p, 0, 23);
11493 if np == p { return core::ptr::null_mut(); }
11494 (*tm).tm_hour = v;
11495 p = np;
11496 }
11497 b'j' => {
11498 let (v, np) = parse_range(p, 1, 366);
11499 if np == p { return core::ptr::null_mut(); }
11500 (*tm).tm_yday = v - 1;
11501 p = np;
11502 }
11503 b'm' => {
11504 let (v, np) = parse_range(p, 1, 12);
11505 if np == p { return core::ptr::null_mut(); }
11506 (*tm).tm_mon = v - 1;
11507 p = np;
11508 }
11509 b'M' => {
11510 let (v, np) = parse_range(p, 0, 59);
11511 if np == p { return core::ptr::null_mut(); }
11512 (*tm).tm_min = v;
11513 p = np;
11514 }
11515 b'n' | b't' => {
11516 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11517 }
11518 b'p' => {
11519 if match_ci_prefix(p, b"AM") {
11520 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
11521 p = p.add(2);
11522 } else if match_ci_prefix(p, b"PM") {
11523 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
11524 p = p.add(2);
11525 } else { return core::ptr::null_mut(); }
11526 }
11527 b'r' => {
11528 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
11529 if r.is_null() { return core::ptr::null_mut(); }
11530 p = r as *const u8;
11531 }
11532 b'R' => {
11533 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
11534 if r.is_null() { return core::ptr::null_mut(); }
11535 p = r as *const u8;
11536 }
11537 b's' => {
11538 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11539 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
11540 let mut val = 0i64;
11541 while *p >= b'0' && *p <= b'9' {
11542 val = val * 10 + (*p - b'0') as i64;
11543 p = p.add(1);
11544 }
11545 if neg { val = -val; }
11546 secs_to_tm(val, &mut *tm);
11547 }
11548 b'S' => {
11549 let (v, np) = parse_range(p, 0, 60);
11550 if np == p { return core::ptr::null_mut(); }
11551 (*tm).tm_sec = v;
11552 p = np;
11553 }
11554 b'T' => {
11555 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
11556 if r.is_null() { return core::ptr::null_mut(); }
11557 p = r as *const u8;
11558 }
11559 b'U' | b'W' => {
11560 let (_, np) = parse_range(p, 0, 53);
11561 if np == p { return core::ptr::null_mut(); }
11562 p = np;
11563 }
11564 b'V' => {
11565 let (_, np) = parse_range(p, 1, 53);
11566 if np == p { return core::ptr::null_mut(); }
11567 p = np;
11568 }
11569 b'w' => {
11570 let (v, np) = parse_range(p, 0, 6);
11571 if np == p { return core::ptr::null_mut(); }
11572 (*tm).tm_wday = v;
11573 p = np;
11574 }
11575 b'y' => {
11576 let (v, np) = parse_int(p, 2);
11577 if np == p { return core::ptr::null_mut(); }
11578 relyear = v;
11579 want_century |= 1;
11580 p = np;
11581 }
11582 b'Y' => {
11583 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11584 let (v, np) = parse_int(p, 4);
11585 if np == p { return core::ptr::null_mut(); }
11586 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
11587 want_century = 0;
11588 p = np;
11589 }
11590 b'z' => {
11591 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
11592 let neg = *p == b'-';
11593 p = p.add(1);
11594 let mut off = 0i64;
11595 let mut digits = 0;
11596 while digits < 4 && *p >= b'0' && *p <= b'9' {
11597 off = off * 10 + (*p - b'0') as i64;
11598 p = p.add(1);
11599 digits += 1;
11600 }
11601 if digits == 0 { return core::ptr::null_mut(); }
11602 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
11603 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
11604 }
11605 b'%' => {
11606 if *p != b'%' { return core::ptr::null_mut(); }
11607 p = p.add(1);
11608 }
11609 _ => { return core::ptr::null_mut(); }
11610 }
11611 f = f.add(1);
11612 }
11613 if want_century != 0 {
11614 (*tm).tm_year = relyear;
11615 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
11616 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
11617 }
11618 p as *mut c_char
11619}
11620
11621#[no_mangle]
11626pub static mut daylight: c_int = 0;
11627#[no_mangle]
11628pub static mut timezone: c_long = 0;
11629#[no_mangle]
11630pub static mut tzname: [*mut c_char; 2] = [b"UTC\0".as_ptr() as *mut c_char, b"UTC\0".as_ptr() as *mut c_char];
11631
11632#[no_mangle]
11633pub unsafe extern "C" fn tzset() {
11634 daylight = 0;
11635 timezone = 0;
11636}
11637
11638#[no_mangle]
11643pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
11644 if cmd.is_null() {
11645 let pid = sys_fork();
11647 if pid == 0 {
11648 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11649 let dash_c = b"-c\0".as_ptr() as *const c_char;
11650 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
11651 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
11652 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11653 _exit(127);
11654 }
11655 if pid < 0 { return -1; }
11656 let mut status: c_int = 0;
11657 loop {
11658 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11659 if r >= 0 { return status; }
11660 if r != -4 { return -1; } }
11662 }
11663
11664 let sa_ignore = sigaction {
11665 sa_handler: SIG_IGN,
11666 sa_flags: SA_RESTORER,
11667 sa_restorer: sig_restorer as *const () as usize,
11668 sa_mask: [0],
11669 };
11670 let mut oldint: sigaction = core::mem::zeroed();
11671 let mut oldquit: sigaction = core::mem::zeroed();
11672
11673 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
11674 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
11675
11676 let mut block_set: SigSetT = 0;
11677 block_set |= 1u64 << (SIGCHLD - 1);
11678 let mut oldmask: SigSetT = 0;
11679 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
11680
11681 let pid = sys_fork();
11682
11683 if pid == 0 {
11684 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11685 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11686 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11687
11688 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11689 let argv = [
11690 b"sh\0".as_ptr() as *const c_char,
11691 b"-c\0".as_ptr() as *const c_char,
11692 cmd,
11693 core::ptr::null(),
11694 ];
11695 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11696 _exit(127);
11697 }
11698
11699 let mut status: c_int = -1;
11700 if pid > 0 {
11701 loop {
11702 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11703 if r >= 0 { break; }
11704 if r != -4 { break; } }
11706 }
11707
11708 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11709 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11710 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11711
11712 status
11713}
11714
11715const EPERM_VAL: c_int = 1;
11720const ENOENT_VAL: c_int = 2;
11721const ESRCH_VAL: c_int = 3;
11722const EINTR_VAL: c_int = 4;
11723const EIO_VAL: c_int = 5;
11724const ENXIO_VAL: c_int = 6;
11725const E2BIG_VAL: c_int = 7;
11726const ENOEXEC_VAL: c_int = 8;
11727const EBADF_VAL: c_int = 9;
11728const ECHILD_VAL: c_int = 10;
11729const EAGAIN_VAL: c_int = 11;
11730const ENOMEM_VAL: c_int = 12;
11731const EACCES_VAL: c_int = 13;
11732const EFAULT_VAL: c_int = 14;
11733const ENOTBLK_VAL: c_int = 15;
11734const EBUSY_VAL: c_int = 16;
11735const EEXIST_VAL: c_int = 17;
11736const EXDEV_VAL: c_int = 18;
11737const ENODEV_VAL: c_int = 19;
11738const ENOTDIR_VAL: c_int = 20;
11739const EISDIR_VAL: c_int = 21;
11740const EINVAL_VAL: c_int = 22;
11741const ENFILE_VAL: c_int = 23;
11742const EMFILE_VAL: c_int = 24;
11743const ENOTTY_VAL: c_int = 25;
11744const ETXTBSY_VAL: c_int = 26;
11745const EFBIG_VAL: c_int = 27;
11746const ENOSPC_VAL: c_int = 28;
11747const ESPIPE_VAL: c_int = 29;
11748const EROFS_VAL: c_int = 30;
11749const EMLINK_VAL: c_int = 31;
11750const EPIPE_VAL: c_int = 32;
11751const EDOM_VAL: c_int = 33;
11752const ERANGE_VAL: c_int = 34;
11753const EDEADLK_VAL: c_int = 35;
11754const ENAMETOOLONG_VAL: c_int = 36;
11755const ENOLCK_VAL: c_int = 37;
11756const ENOSYS_VAL: c_int = 38;
11757const ENOTEMPTY_VAL: c_int = 39;
11758const ELOOP_VAL: c_int = 40;
11759const EWOULDBLOCK_VAL: c_int = 11;
11760const ENOMSG_VAL: c_int = 42;
11761const EIDRM_VAL: c_int = 43;
11762const ECHRNG_VAL: c_int = 44;
11763const EL2NSYNC_VAL: c_int = 45;
11764const EL3HLT_VAL: c_int = 46;
11765const EL3RST_VAL: c_int = 47;
11766const ELNRNG_VAL: c_int = 48;
11767const EUNATCH_VAL: c_int = 49;
11768const ENOCSI_VAL: c_int = 50;
11769const EL2HLT_VAL: c_int = 51;
11770const EBADE_VAL: c_int = 52;
11771const EBADR_VAL: c_int = 53;
11772const EXFULL_VAL: c_int = 54;
11773const ENOANO_VAL: c_int = 55;
11774const EBADRQC_VAL: c_int = 56;
11775const EBADSLT_VAL: c_int = 57;
11776const EBFONT_VAL: c_int = 59;
11777const ENOSTR_VAL: c_int = 60;
11778const ENODATA_VAL: c_int = 61;
11779const ETIME_VAL: c_int = 62;
11780const ENOSR_VAL: c_int = 63;
11781const ENONET_VAL: c_int = 64;
11782const ENOPKG_VAL: c_int = 65;
11783const EREMOTE_VAL: c_int = 66;
11784const ENOLINK_VAL: c_int = 67;
11785const EADV_VAL: c_int = 68;
11786const ESRMNT_VAL: c_int = 69;
11787const ECOMM_VAL: c_int = 70;
11788const EPROTO_VAL: c_int = 71;
11789const EMULTIHOP_VAL: c_int = 72;
11790const EDOTDOT_VAL: c_int = 73;
11791const EBADMSG_VAL: c_int = 74;
11792const EOVERFLOW_VAL: c_int = 75;
11793const ENOTUNIQ_VAL: c_int = 76;
11794const EBADFD_VAL: c_int = 77;
11795const EREMCHG_VAL: c_int = 78;
11796const ELIBACC_VAL: c_int = 79;
11797const ELIBBAD_VAL: c_int = 80;
11798const ELIBSCN_VAL: c_int = 81;
11799const ELIBMAX_VAL: c_int = 82;
11800const ELIBEXEC_VAL: c_int = 83;
11801const EILSEQ_VAL: c_int = 84;
11802const ERESTART_VAL: c_int = 85;
11803const ESTRPIPE_VAL: c_int = 86;
11804const EUSERS_VAL: c_int = 87;
11805const ENOTSOCK_VAL: c_int = 88;
11806const EDESTADDRREQ_VAL: c_int = 89;
11807const EMSGSIZE_VAL: c_int = 90;
11808const EPROTOTYPE_VAL: c_int = 91;
11809const ENOPROTOOPT_VAL: c_int = 92;
11810const EPROTONOSUPPORT_VAL: c_int = 93;
11811const ESOCKTNOSUPPORT_VAL: c_int = 94;
11812const EOPNOTSUPP_VAL: c_int = 95;
11813const ENOTSUP_VAL: c_int = 95;
11814const EPFNOSUPPORT_VAL: c_int = 96;
11815const EAFNOSUPPORT_VAL: c_int = 97;
11816const EADDRINUSE_VAL: c_int = 98;
11817const EADDRNOTAVAIL_VAL: c_int = 99;
11818const ENETDOWN_VAL: c_int = 100;
11819const ENETUNREACH_VAL: c_int = 101;
11820const ENETRESET_VAL: c_int = 102;
11821const ECONNABORTED_VAL: c_int = 103;
11822const ECONNRESET_VAL: c_int = 104;
11823const ENOBUFS_VAL: c_int = 105;
11824const EISCONN_VAL: c_int = 106;
11825const ENOTCONN_VAL: c_int = 107;
11826const ESHUTDOWN_VAL: c_int = 108;
11827const ETOOMANYREFS_VAL: c_int = 109;
11828const ETIMEDOUT_VAL: c_int = 110;
11829const ECONNREFUSED_VAL: c_int = 111;
11830const EHOSTDOWN_VAL: c_int = 112;
11831const EHOSTUNREACH_VAL: c_int = 113;
11832const EALREADY_VAL: c_int = 114;
11833const EINPROGRESS_VAL: c_int = 115;
11834const ESTALE_VAL: c_int = 116;
11835const EUCLEAN_VAL: c_int = 117;
11836const ENOTNAM_VAL: c_int = 118;
11837const ENAVAIL_VAL: c_int = 119;
11838const EISNAM_VAL: c_int = 120;
11839const EREMOTEIO_VAL: c_int = 121;
11840const EDQUOT_VAL: c_int = 122;
11841const ENOMEDIUM_VAL: c_int = 123;
11842const EMEDIUMTYPE_VAL: c_int = 124;
11843const ECANCELED_VAL: c_int = 125;
11844const ENOKEY_VAL: c_int = 126;
11845const EKEYEXPIRED_VAL: c_int = 127;
11846const EKEYREVOKED_VAL: c_int = 128;
11847const EKEYREJECTED_VAL: c_int = 129;
11848const EOWNERDEAD_VAL: c_int = 130;
11849const ENOTRECOVERABLE_VAL: c_int = 131;
11850const ERFKILL_VAL: c_int = 132;
11851const EHWPOISON_VAL: c_int = 133;
11852
11853static ERR_STRS: [&[u8]; 134] = [
11855 b"Success\0", b"Operation not permitted\0", b"No such file or directory\0", b"No such process\0", b"Interrupted system call\0", b"Input/output error\0", b"No such device or address\0", b"Argument list too long\0", b"Exec format error\0", b"Bad file descriptor\0", b"No child processes\0", b"Resource temporarily unavailable\0", b"Cannot allocate memory\0", b"Permission denied\0", b"Bad address\0", b"Block device required\0", b"Device or resource busy\0", b"File exists\0", b"Invalid cross-device link\0", b"No such device\0", b"Not a directory\0", b"Is a directory\0", b"Invalid argument\0", b"Too many open files in system\0", b"Too many open files\0", b"Inappropriate ioctl for device\0", b"Text file busy\0", b"File too large\0", b"No space left on device\0", b"Illegal seek\0", b"Read-only file system\0", b"Too many links\0", b"Broken pipe\0", b"Numerical argument out of domain\0", b"Numerical result out of range\0", b"Resource deadlock avoided\0", b"File name too long\0", b"No locks available\0", b"Function not implemented\0", b"Directory not empty\0", b"Too many levels of symbolic links\0", b"Unknown error 41\0", b"No message of desired type\0", b"Identifier removed\0", b"Channel number out of range\0", b"Level 2 not synchronized\0", b"Level 3 halted\0", b"Level 3 reset\0", b"Link number out of range\0", b"Protocol driver not attached\0", b"No CSI structure available\0", b"Level 2 halted\0", b"Invalid exchange\0", b"Invalid request descriptor\0", b"Exchange full\0", b"No anode\0", b"Invalid request code\0", b"Invalid slot\0", b"Unknown error 58\0", b"Bad font file format\0", b"Device not a stream\0", b"No data available\0", b"Timer expired\0", b"Out of streams resources\0", b"Machine is not on the network\0", b"Package not installed\0", b"Object is remote\0", b"Link has been severed\0", b"Advertise error\0", b"Srmount error\0", b"Communication error on send\0", b"Protocol error\0", b"Multihop attempted\0", b"RFS specific error\0", b"Bad message\0", b"Value too large for defined data type\0", b"Name not unique on network\0", b"File descriptor in bad state\0", b"Remote address changed\0", b"Can not access a needed shared library\0", b"Accessing a corrupted shared library\0", b".lib section in a.out corrupted\0", b"Attempting to link in too many shared libraries\0", b"Cannot exec a shared library directly\0", b"Invalid or incomplete multibyte or wide character\0", b"Interrupted system call should be restarted\0", b"Streams pipe error\0", b"Too many users\0", b"Socket operation on non-socket\0", b"Destination address required\0", b"Message too long\0", b"Protocol wrong type for socket\0", b"Protocol not available\0", b"Protocol not supported\0", b"Socket type not supported\0", b"Operation not supported\0", b"Protocol family not supported\0", b"Address family not supported by protocol\0", b"Address already in use\0", b"Cannot assign requested address\0", b"Network is down\0", b"Network is unreachable\0", b"Network dropped connection on reset\0", b"Software caused connection abort\0", b"Connection reset by peer\0", b"No buffer space available\0", b"Transport endpoint is already connected\0", b"Transport endpoint is not connected\0", b"Cannot send after transport endpoint shutdown\0", b"Too many references: cannot splice\0", b"Connection timed out\0", b"Connection refused\0", b"Host is down\0", b"No route to host\0", b"Operation already in progress\0", b"Operation now in progress\0", b"Stale file handle\0", b"Structure needs cleaning\0", b"Not a XENIX named type file\0", b"No XENIX semaphores available\0", b"Is a named type file\0", b"Remote I/O error\0", b"Quota exceeded\0", b"No medium found\0", b"Wrong medium type\0", b"Operation canceled\0", b"Required key not available\0", b"Key has expired\0", b"Key has been revoked\0", b"Key was rejected by service\0", b"Owner died\0", b"State not recoverable\0", b"Operation not possible due to RF-kill\0", b"Memory page has hardware error\0", ];
11990
11991#[no_mangle]
11992pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
11993 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
11994 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
11996 let prefix = b"Unknown error \0";
11997 let mut i = 0;
11998 while prefix[i] != 0 {
11999 UNKNOWN_BUF[i] = prefix[i] as c_char;
12000 i += 1;
12001 }
12002 let (buf, len) = format_u64(errnum as u64);
12003 for j in 0..len {
12004 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12005 i += 1;
12006 }
12007 UNKNOWN_BUF[i] = 0;
12008 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12009 }
12010 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12011}
12012
12013#[no_mangle]
12014pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12015 let s = strerror(errnum);
12016 let slen = strlen(s as *const c_char);
12017 if slen >= buflen {
12018 if buflen > 0 {
12019 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12020 *buf.add(buflen - 1) = 0;
12021 }
12022 return 34; }
12024 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12025 0
12026}
12027
12028#[no_mangle]
12030pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12031
12032unsafe fn sync_environ() {
12034 environ = __environ;
12035}
12036
12037#[inline]
12042unsafe fn sys_dup(oldfd: i32) -> i64 {
12043 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12044}
12045
12046#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12047 sys_dup3(oldfd, newfd, 0)
12049}
12050
12051#[inline]
12052unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12053 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12054}
12055
12056#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12057 sys_unlinkat(AT_FDCWD, path, 0)
12058}
12059
12060#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12061 sys_unlinkat(AT_FDCWD, path, 512) }
12063
12064#[inline]
12065unsafe fn sys_chdir(path: *const u8) -> i64 {
12066 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12067}
12068
12069#[inline]
12070unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12071 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12072}
12073
12074#[inline]
12075unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12076 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12077}
12078
12079#[inline]
12080unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12081 #[repr(C)]
12082 struct UtsName {
12083 sysname: [u8; 65],
12084 nodename: [u8; 65],
12085 release: [u8; 65],
12086 version: [u8; 65],
12087 machine: [u8; 65],
12088 domainname: [u8; 65],
12089 }
12090 let mut uts: UtsName = core::mem::zeroed();
12091 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12092 if result < 0 {
12093 return result;
12094 }
12095 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12096 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12097 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12098 if len > 0 { *buf.add(copylen) = 0; }
12099 0
12100}
12101
12102unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12103 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12104}
12105
12106unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12107 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12108}
12109
12110unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12111 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12112}
12113
12114const ITIMER_REAL: i32 = 0;
12115
12116#[repr(C)]
12117struct itimerval {
12118 it_interval: timeval,
12119 it_value: timeval,
12120}
12121
12122unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12123 let mut new: itimerval = core::mem::zeroed();
12124 new.it_value.tv_sec = seconds as c_long;
12125 let mut old: itimerval = core::mem::zeroed();
12126 let r = <Arch as Syscalls>::syscall3(
12127 SYS_SETITIMER,
12128 ITIMER_REAL as i64,
12129 &new as *const _ as i64,
12130 &mut old as *mut _ as i64,
12131 );
12132 if r < 0 {
12133 return r;
12134 }
12135 old.it_value.tv_sec as i64
12136}
12137
12138unsafe fn sys_pause() -> i64 {
12139 #[cfg(target_arch = "x86_64")]
12140 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12141 #[cfg(target_arch = "aarch64")]
12142 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12143 #[cfg(target_arch = "riscv64")]
12144 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12145}
12146
12147unsafe fn sys_fsync(fd: i32) -> i64 {
12148 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12149}
12150
12151unsafe fn sys_fdatasync(fd: i32) -> i64 {
12152 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12153}
12154
12155unsafe fn sys_sync() {
12156 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12157}
12158
12159unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12160 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12161}
12162
12163unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12164 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12165}
12166
12167unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12168 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12169}
12170
12171unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12172 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12173}
12174
12175unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12176 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12177}
12178
12179unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12180 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12181}
12182
12183unsafe fn sys_umask(mask: u32) -> u32 {
12184 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12185}
12186
12187unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12188 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12189}
12190
12191unsafe fn sys_setuid(uid: c_uint) -> i64 {
12192 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12193}
12194
12195unsafe fn sys_setgid(gid: c_uint) -> i64 {
12196 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12197}
12198
12199unsafe fn sys_setsid() -> i64 {
12200 <Arch as Syscalls>::syscall0(SYS_SETSID)
12201}
12202
12203unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12204 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12205}
12206
12207unsafe fn sys_getpgid(pid: c_int) -> i64 {
12208 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12209}
12210
12211unsafe fn sys_getsid(pid: c_int) -> i64 {
12212 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12213}
12214
12215unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12216 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12217}
12218
12219#[no_mangle]
12222pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12223 let r = sys_pipe2(fds, 0);
12224 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12225 0
12226}
12227
12228#[no_mangle]
12229pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12230 let r = sys_pipe2(fds, flags);
12231 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12232 0
12233}
12234
12235#[no_mangle]
12236pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12237 let r = sys_dup(oldfd);
12238 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12239 r as c_int
12240}
12241
12242#[no_mangle]
12243pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12244 let r = sys_dup2(oldfd, newfd);
12245 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12246 r as c_int
12247}
12248
12249#[no_mangle]
12250pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12251 let r = sys_dup3(oldfd, newfd, flags);
12252 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12253 r as c_int
12254}
12255
12256#[no_mangle]
12257pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12258 let r = match cmd {
12259 F_GETFD | F_GETFL => sys_fcntl(fd, cmd, 0),
12260 F_SETFD | F_SETFL | F_DUPFD | F_DUPFD_CLOEXEC => {
12261 let arg = args.next_arg::<c_int>();
12262 sys_fcntl(fd, cmd, arg as i64)
12263 }
12264 F_GETLK | F_SETLK | F_SETLKW => {
12265 let arg = args.next_arg::<*mut c_void>();
12266 sys_fcntl(fd, cmd, arg as i64)
12267 }
12268 _ => sys_fcntl(fd, cmd, 0),
12269 };
12270 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12271 r as c_int
12272}
12273
12274#[no_mangle]
12275pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12276 let r = sys_access(path as *const u8, mode);
12277 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12278 0
12279}
12280
12281#[no_mangle]
12282pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12283 let r = sys_unlink(path as *const u8);
12284 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12285 0
12286}
12287
12288#[no_mangle]
12289pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12290 let r = sys_rmdir(path as *const u8);
12291 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12292 0
12293}
12294
12295#[no_mangle]
12296pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12297 let r = sys_chdir(path as *const u8);
12298 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12299 0
12300}
12301
12302#[no_mangle]
12303pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12304 if buf.is_null() {
12305 let alloc_size = if size == 0 { 256 } else { size };
12307 let p = malloc(alloc_size) as *mut c_char;
12308 if p.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
12309 let r = sys_getcwd(p as *mut u8, alloc_size);
12310 if r < 0 { free(p as *mut c_void); ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12311 return p;
12312 }
12313 if size == 0 { ERRNO = EINVAL; return core::ptr::null_mut(); }
12314 let r = sys_getcwd(buf as *mut u8, size);
12315 if r < 0 { ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12316 buf
12317}
12318
12319#[no_mangle]
12320pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12321 let r = sys_gethostname(name as *mut u8, len);
12322 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12323 0
12324}
12325
12326#[no_mangle]
12328pub extern "C" fn getpagesize() -> c_int {
12329 4096
12330}
12331
12332#[no_mangle]
12333pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12334 let r = sys_truncate(path as *const u8, length);
12335 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12336 0
12337}
12338
12339#[no_mangle]
12340pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12341 let r = sys_ftruncate(fd, length);
12342 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12343 0
12344}
12345
12346#[no_mangle]
12347pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12348 pthread_testcancel();
12349 let r = sys_nanosleep(req, rem);
12350 pthread_testcancel();
12351 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12352 0
12353}
12354
12355#[no_mangle]
12356pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12357 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12358 let mut rem: timespec = core::mem::zeroed();
12359 pthread_testcancel();
12360 let r = sys_nanosleep(&req, &mut rem);
12361 pthread_testcancel();
12362 if r < 0 {
12363 let e = (-r) as c_int;
12364 if e == EINTR { return rem.tv_sec as c_uint; }
12365 }
12366 0
12367}
12368
12369#[no_mangle]
12370pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12371 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12372 pthread_testcancel();
12373 let r = sys_nanosleep(&req, core::ptr::null_mut());
12374 pthread_testcancel();
12375 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12376 0
12377}
12378
12379#[no_mangle]
12380pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12381 sys_alarm(seconds) as c_uint
12382}
12383
12384#[no_mangle]
12385pub unsafe extern "C" fn pause() -> c_int {
12386 pthread_testcancel();
12387 sys_pause();
12388 pthread_testcancel();
12389 ERRNO = EINTR;
12390 -1
12391}
12392
12393#[no_mangle]
12394pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12395 let r = sys_fsync(fd);
12396 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12397 0
12398}
12399
12400#[no_mangle]
12401pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12402 let r = sys_fdatasync(fd);
12403 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12404 0
12405}
12406
12407#[no_mangle]
12408pub unsafe extern "C" fn sync() {
12409 sys_sync();
12410}
12411
12412#[no_mangle]
12413pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12414 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12415 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12416 0
12417}
12418
12419#[no_mangle]
12420pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12421 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12422 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12423 r as isize
12424}
12425
12426#[no_mangle]
12427pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12428 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12429 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12430 0
12431}
12432
12433#[no_mangle]
12434pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
12435 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
12436 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12437 0
12438}
12439
12440#[no_mangle]
12441pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
12442 let r = sys_fchmod(fd, mode);
12443 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12444 0
12445}
12446
12447#[no_mangle]
12448pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
12449 sys_umask(mask) as c_uint
12450}
12451
12452#[no_mangle]
12453pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
12454 let mut ws: winsize = core::mem::zeroed();
12455 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
12456}
12457
12458#[no_mangle]
12460pub unsafe extern "C" fn ttyname(_fd: c_int) -> *mut c_char {
12461 core::ptr::null_mut()
12462}
12463
12464#[no_mangle]
12466pub unsafe extern "C" fn getlogin() -> *mut c_char {
12467 b"root\0".as_ptr() as *mut c_char
12468}
12469
12470#[no_mangle]
12471pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
12472 let r = sys_getgroups(size, list);
12473 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12474 r as c_int
12475}
12476
12477#[no_mangle]
12478pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
12479 let r = sys_setuid(uid);
12480 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12481 0
12482}
12483
12484#[no_mangle]
12485pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
12486 let r = sys_setgid(gid);
12487 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12488 0
12489}
12490
12491#[no_mangle]
12492pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
12493 let r = sys_setuid(euid);
12495 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12496 0
12497}
12498
12499#[no_mangle]
12500pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
12501 let r = sys_setgid(egid);
12502 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12503 0
12504}
12505
12506#[no_mangle]
12507pub unsafe extern "C" fn setreuid(_ruid: c_uint, _euid: c_uint) -> c_int {
12508 0
12510}
12511
12512#[no_mangle]
12513pub unsafe extern "C" fn setregid(_rgid: c_uint, _egid: c_uint) -> c_int {
12514 0
12515}
12516
12517#[no_mangle]
12518pub unsafe extern "C" fn setsid() -> c_int {
12519 let r = sys_setsid();
12520 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12521 r as c_int
12522}
12523
12524#[no_mangle]
12525pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
12526 let r = sys_setpgid(pid, pgid);
12527 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12528 0
12529}
12530
12531#[no_mangle]
12532pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
12533 let r = sys_getpgid(pid);
12534 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12535 r as c_int
12536}
12537
12538#[no_mangle]
12539pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
12540 let r = sys_getsid(pid);
12541 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12542 r as c_int
12543}
12544
12545#[no_mangle]
12546pub unsafe extern "C" fn getpgrp() -> c_int {
12547 sys_getpgid(0) as c_int
12548}
12549
12550#[no_mangle]
12551pub unsafe extern "C" fn setpgrp() -> c_int {
12552 setpgid(0, 0)
12553}
12554
12555#[no_mangle]
12556pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
12557 if template.is_null() { ERRNO = EINVAL; return -1; }
12558 let len = strlen(template as *const c_char);
12559 if len < 6 { ERRNO = EINVAL; return -1; }
12560 let x_start = len - 6;
12561 for i in x_start..len {
12563 if *template.add(i) != b'X' as c_char { ERRNO = EINVAL; return -1; }
12564 }
12565 let mut ts: timespec = core::mem::zeroed();
12566 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
12567 let mut ctr: u32 = ts.tv_nsec as u32;
12568 for _ in 0..100 {
12569 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
12570 let seed = ctr;
12571 let hex = b"0123456789abcdef";
12573 let mut s = seed;
12574 for i in x_start..len {
12575 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
12576 s >>= 4;
12577 }
12578 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
12579 if fd >= 0 { return fd as c_int; }
12580 let e = (-fd) as c_int;
12581 if e != EEXIST_VAL { ERRNO = e; return -1; }
12582 }
12583 ERRNO = EEXIST_VAL;
12584 -1
12585}
12586
12587#[no_mangle]
12588pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
12589 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
12590 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12591 0
12592}
12593
12594#[no_mangle]
12599pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
12600 if s.is_null() || *s == 0 {
12601 return b".\0".as_ptr() as *mut c_char;
12602 }
12603 let mut i = strlen(s as *const c_char);
12604 i = i.wrapping_sub(1);
12605 while i > 0 && *s.add(i) == b'/' as c_char {
12607 i = i.wrapping_sub(1);
12608 }
12609 if i == 0 && *s.add(0) == b'/' as c_char {
12610 return b"/\0".as_ptr() as *mut c_char;
12611 }
12612 while i > 0 && *s.add(i) != b'/' as c_char {
12614 i = i.wrapping_sub(1);
12615 }
12616 if i == 0 {
12617 if *s.add(0) == b'/' as c_char {
12618 return b"/\0".as_ptr() as *mut c_char;
12619 }
12620 return b".\0".as_ptr() as *mut c_char;
12621 }
12622 while i > 0 && *s.add(i - 1) == b'/' as c_char {
12624 i = i.wrapping_sub(1);
12625 }
12626 if i == 0 {
12627 return b"/\0".as_ptr() as *mut c_char;
12628 }
12629 *s.add(i) = 0;
12630 s
12631}
12632
12633#[no_mangle]
12634pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
12635 if s.is_null() || *s == 0 {
12636 return b".\0".as_ptr() as *mut c_char;
12637 }
12638 let mut i = strlen(s as *const c_char);
12639 i = i.wrapping_sub(1);
12640 while i > 0 && *s.add(i) == b'/' as c_char {
12642 *s.add(i) = 0;
12643 i = i.wrapping_sub(1);
12644 }
12645 while i > 0 && *s.add(i - 1) != b'/' as c_char {
12647 i = i.wrapping_sub(1);
12648 }
12649 s.add(i)
12650}
12651
12652const AF_INET_VAL: c_int = 2;
12657const AF_INET6_VAL: c_int = 10;
12658const EAFNOSUPPORT: c_int = 97;
12659const ENOSPC_VAL2: c_int = 28;
12660
12661unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
12662 let mut p = s;
12663 let mut i = 0;
12664 while i < 4 {
12665 let oct_start = p;
12666 let mut v: u32 = 0;
12667 let mut j: u32 = 0;
12668 while j < 3 && *p >= b'0' && *p <= b'9' {
12669 v = v * 10 + (*p - b'0') as u32;
12670 p = p.add(1);
12671 j += 1;
12672 }
12673 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
12674 *a.add(i) = v as u8;
12675 if *p == 0 && i == 3 { return 1; }
12676 if *p != b'.' { return 0; }
12677 p = p.add(1);
12678 i += 1;
12679 }
12680 0
12681}
12682
12683unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
12684 let mut ip = [0u16; 8];
12685 let mut p = s;
12686 let mut i: usize = 0;
12687 let mut brk: isize = -1;
12688 let mut need_v4 = false;
12689 let mut v4_start: *const u8 = core::ptr::null();
12690
12691 if *p == b':' {
12692 p = p.add(1);
12693 if *p != b':' { return 0; }
12694 }
12695
12696 loop {
12697 if *p == b':' && brk < 0 {
12698 brk = i as isize;
12699 ip[i & 7] = 0;
12700 p = p.add(1);
12701 if *p == 0 { break; }
12702 if i == 7 { return 0; }
12703 i += 1;
12704 continue;
12705 }
12706 v4_start = p;
12707 let mut v: u16 = 0;
12708 let mut j = 0;
12709 while j < 4 {
12710 let d = hex_digit(*p);
12711 if d < 0 { break; }
12712 v = v * 16 + d as u16;
12713 p = p.add(1);
12714 j += 1;
12715 }
12716 if j == 0 { return 0; }
12717 ip[i & 7] = v;
12718 if *p == 0 && (brk >= 0 || i == 7) { break; }
12719 if i == 7 { return 0; }
12720 if *p != b':' {
12721 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
12722 need_v4 = true;
12723 i += 1;
12724 ip[i & 7] = 0;
12725 break;
12726 }
12727 p = p.add(1);
12728 i += 1;
12729 }
12730
12731 if brk >= 0 {
12732 let trail_count = i + 1 - brk as usize;
12734 let dest_start = brk as usize + 7 - i;
12735 for j in (0..trail_count).rev() {
12737 ip[dest_start + j] = ip[brk as usize + j];
12738 }
12739 for j in 0..(7 - i) {
12740 ip[brk as usize + j] = 0;
12741 }
12742 }
12743
12744 for k in 0..8 {
12745 *a.add(k * 2) = (ip[k] >> 8) as u8;
12746 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
12747 }
12748
12749 if need_v4 {
12750 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
12751 }
12752 1
12753}
12754
12755unsafe fn hex_digit(c: u8) -> i32 {
12756 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
12757 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
12758 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
12759 else { -1 }
12760}
12761
12762#[no_mangle]
12763pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
12764 if af == AF_INET_VAL {
12765 inet_pton_v4(s as *const u8, a as *mut u8)
12766 } else if af == AF_INET6_VAL {
12767 inet_pton_v6(s as *const u8, a as *mut u8)
12768 } else {
12769 ERRNO = EAFNOSUPPORT;
12770 -1
12771 }
12772}
12773
12774#[no_mangle]
12775pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
12776 if af == AF_INET_VAL {
12777 let b = a as *const u8;
12778 let needed = 16; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
12780 let mut pos = 0;
12781 for i in 0..4 {
12782 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
12783 let (buf, len) = format_u64(*b.add(i) as u64);
12784 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
12785 }
12786 *s.add(pos) = 0;
12787 s
12788 } else if af == AF_INET6_VAL {
12789 let b = a as *const u8;
12790 let needed = 46; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
12792 let mut words = [0u16; 8];
12793 for i in 0..8 {
12794 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
12795 }
12796 let mut pos = 0usize;
12798 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
12799 && words[4] == 0 && words[5] == 0xffff
12800 {
12801 let prefix = b"::ffff:";
12802 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
12803 for idx in 0..4 {
12804 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
12805 let octet = *b.add(12 + idx);
12806 if octet >= 100 {
12807 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
12808 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
12809 } else if octet >= 10 {
12810 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
12811 }
12812 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
12813 }
12814 *s.add(pos) = 0;
12815 return s;
12816 }
12817 let mut best_start: isize = -1;
12819 let mut best_len: usize = 0;
12820 let mut j: usize = 0;
12821 while j < 8 {
12822 if words[j] == 0 {
12823 let mut k = j;
12824 while k < 8 && words[k] == 0 { k += 1; }
12825 let run = k - j;
12826 if run > best_len { best_start = j as isize; best_len = run; }
12827 j = k;
12828 } else {
12829 j += 1;
12830 }
12831 }
12832 let mut i: usize = 0;
12833 let mut prev_in_run = false;
12834 while i < 8 {
12835 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
12836 if in_run {
12837 if i == best_start as usize {
12838 *s.add(pos) = b':' as c_char; pos += 1;
12839 *s.add(pos) = b':' as c_char; pos += 1;
12840 }
12841 i += 1;
12842 prev_in_run = true;
12843 continue;
12844 }
12845 if i > 0 && !prev_in_run {
12846 *s.add(pos) = b':' as c_char; pos += 1;
12847 }
12848 let (buf, len) = format_hex(words[i] as u64, false);
12849 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
12850 i += 1;
12851 prev_in_run = false;
12852 }
12853 *s.add(pos) = 0;
12854 s
12855 } else {
12856 ERRNO = EAFNOSUPPORT;
12857 core::ptr::null_mut()
12858 }
12859}
12860
12861#[no_mangle]
12862pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
12863 let a = dest as *mut u8;
12864 let mut p = s as *const u8;
12865 let mut vals = [0u64; 4];
12866 let mut i = 0usize;
12867 while i < 4 {
12868 if *p < b'0' || *p > b'9' { return 0; }
12869 let mut base = 10u32;
12870 if *p == b'0' {
12871 let c = *p.add(1);
12872 if c == b'x' || c == b'X' {
12873 base = 16;
12874 p = p.add(2);
12875 if !((*p >= b'0' && *p <= b'9')
12876 || (*p >= b'a' && *p <= b'f')
12877 || (*p >= b'A' && *p <= b'F')) {
12878 return 0;
12879 }
12880 } else {
12881 base = 8;
12882 }
12883 }
12884 let mut v: u64 = 0;
12885 let start = p;
12886 loop {
12887 let c = *p;
12888 let d = if c >= b'0' && c <= b'9' {
12889 (c - b'0') as u64
12890 } else if base == 16 && c >= b'a' && c <= b'f' {
12891 (c - b'a' + 10) as u64
12892 } else if base == 16 && c >= b'A' && c <= b'F' {
12893 (c - b'A' + 10) as u64
12894 } else {
12895 break;
12896 };
12897 v = v * (base as u64) + d;
12898 p = p.add(1);
12899 }
12900 if p == start { return 0; }
12901 vals[i] = v;
12902 if *p == 0 {
12903 break;
12904 }
12905 if *p != b'.' || i == 3 { return 0; }
12906 p = p.add(1);
12907 i += 1;
12908 }
12909 if i == 4 { return 0; }
12910 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
12911 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
12912 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
12913 for j in 0..4 {
12914 if vals[j] > 255 { return 0; }
12915 *a.add(j) = vals[j] as u8;
12916 }
12917 1
12918}
12919
12920#[no_mangle]
12921pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
12922 let mut a = [0u8; 4];
12923 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
12924 u32::from_ne_bytes(a)
12925 } else {
12926 !0u32 }
12928}
12929
12930#[no_mangle]
12931pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
12932 static mut NTOA_BUF: [c_char; 16] = [0; 16];
12933 let b = addr.to_ne_bytes();
12934 let mut pos = 0;
12935 for i in 0..4 {
12936 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
12937 let (buf, len) = format_u64(b[i] as u64);
12938 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
12939 }
12940 NTOA_BUF[pos] = 0;
12941 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
12942}
12943
12944#[no_mangle]
12946pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
12947 inet_addr(s).to_be()
12948}
12949
12950#[no_mangle]
12951pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
12952 let addr: u32;
12953 if (net as u32) < 128 {
12954 addr = (net as u32) << 24;
12955 } else if (net as u32) < 0x10000 {
12956 addr = (net as u32) << 16;
12957 } else if (net as u32) < 0x1000000 {
12958 addr = (net as u32) << 8;
12959 } else {
12960 addr = net as u32;
12961 }
12962 addr | (host as u32 & 0xffffffff)
12963}
12964
12965#[no_mangle]
12966pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
12967 let h = u32::from_be(addr);
12968 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
12969 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
12970 else { (h & 0x000000ff) as c_int }
12971}
12972
12973#[no_mangle]
12974pub extern "C" fn inet_netof(addr: u32) -> c_int {
12975 let h = u32::from_be(addr);
12976 if h < 0x80000000 { (h >> 24) as c_int }
12977 else if h < 0xc0000000 { (h >> 16) as c_int }
12978 else { (h >> 8) as c_int }
12979}
12980
12981unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
12990 let mut p = s;
12991 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
12993 let mut neg = false;
12994 if *p == b'-' { neg = true; p = p.add(1); }
12995 else if *p == b'+' { p = p.add(1); }
12996
12997 if (*p | 0x20) == b'i'
12999 && (*p.add(1) | 0x20) == b'n'
13000 && (*p.add(2) | 0x20) == b'f'
13001 {
13002 p = p.add(3);
13003 if (*p | 0x20) == b'i'
13005 && (*p.add(1) | 0x20) == b't'
13006 && (*p.add(2) | 0x20) == b'y'
13007 {
13008 p = p.add(3);
13009 }
13010 if !endptr.is_null() { *endptr = p as *mut u8; }
13011 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13012 }
13013 if (*p | 0x20) == b'n'
13015 && (*p.add(1) | 0x20) == b'a'
13016 && (*p.add(2) | 0x20) == b'n'
13017 {
13018 p = p.add(3);
13019 if *p == b'(' {
13021 p = p.add(1);
13022 while *p != 0 && *p != b')' { p = p.add(1); }
13023 if *p == b')' { p = p.add(1); }
13024 }
13025 if !endptr.is_null() { *endptr = p as *mut u8; }
13026 return if neg { -f64::NAN } else { f64::NAN };
13027 }
13028
13029 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13031 p = p.add(2);
13032 let mut mant: u128 = 0;
13033 let mut frac_hex: u32 = 0;
13034 let mut found = false;
13035 let mut in_frac = false;
13036
13037 loop {
13038 if let Some(d) = hex_val(*p) {
13039 if mant <= u128::MAX / 16 {
13040 mant = mant * 16 + d as u128;
13041 }
13042 if in_frac { frac_hex += 1; }
13043 p = p.add(1);
13044 found = true;
13045 } else if *p == b'.' && !in_frac {
13046 in_frac = true;
13047 p = p.add(1);
13048 } else {
13049 break;
13050 }
13051 }
13052
13053 if !found {
13054 if !endptr.is_null() { *endptr = s as *mut u8; }
13055 return 0.0;
13056 }
13057
13058 let mut bin_exp: i32 = 0;
13060 if *p == b'p' || *p == b'P' {
13061 p = p.add(1);
13062 let mut exp_neg = false;
13063 if *p == b'-' { exp_neg = true; p = p.add(1); }
13064 else if *p == b'+' { p = p.add(1); }
13065 while *p >= b'0' && *p <= b'9' {
13066 if bin_exp < 100000 {
13067 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13068 }
13069 p = p.add(1);
13070 }
13071 if exp_neg { bin_exp = -bin_exp; }
13072 }
13073
13074 if !endptr.is_null() { *endptr = p as *mut u8; }
13075 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13076
13077 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13078 return hex_mant_to_f64(mant, total_exp, neg);
13079 }
13080
13081 let mut buf = [0u8; 65536];
13083 let mut n = 0usize;
13084 let mut found_digit = false;
13085
13086 while *p >= b'0' && *p <= b'9' {
13087 if n < 65535 { buf[n] = *p; n += 1; }
13088 p = p.add(1);
13089 found_digit = true;
13090 }
13091 if *p == b'.' {
13092 if n < 65535 { buf[n] = b'.'; n += 1; }
13093 p = p.add(1);
13094 while *p >= b'0' && *p <= b'9' {
13095 if n < 65535 { buf[n] = *p; n += 1; }
13096 p = p.add(1);
13097 found_digit = true;
13098 }
13099 }
13100 if !found_digit {
13101 if !endptr.is_null() { *endptr = s as *mut u8; }
13102 return 0.0;
13103 }
13104 if *p == b'e' || *p == b'E' {
13105 if n < 65535 { buf[n] = b'e'; n += 1; }
13106 p = p.add(1);
13107 if *p == b'-' || *p == b'+' {
13108 if n < 65535 { buf[n] = *p; n += 1; }
13109 p = p.add(1);
13110 }
13111 while *p >= b'0' && *p <= b'9' {
13112 if n < 65535 { buf[n] = *p; n += 1; }
13113 p = p.add(1);
13114 }
13115 }
13116
13117 if !endptr.is_null() { *endptr = p as *mut u8; }
13118 let s_str = core::str::from_utf8_unchecked(
13119 core::slice::from_raw_parts(buf.as_ptr(), n),
13120 );
13121 if is_f32 {
13122 match <f32 as core::str::FromStr>::from_str(s_str) {
13123 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13124 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13125 }
13126 } else {
13127 match <f64 as core::str::FromStr>::from_str(s_str) {
13128 Ok(v) => if neg { -v } else { v },
13129 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13130 }
13131 }
13132}
13133
13134fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13138 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13139
13140 let msb = (127 - mant.leading_zeros()) as i64;
13141 let unbiased_exp = msb + total_exp;
13142 let biased_exp = unbiased_exp + 1023;
13143
13144 if biased_exp >= 2047 {
13146 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13147 }
13148
13149 if biased_exp <= 0 {
13151 let shift = total_exp + 1074;
13154 if shift < 0 {
13155 return if neg { -0.0 } else { 0.0 };
13156 }
13157 if shift > 128 {
13158 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13159 }
13160 let shifted = mant << (shift as u32);
13161 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13162 let guard = ((shifted >> 52) & 1) != 0;
13163 let sticky = (shifted >> 53) != 0;
13164 let mut result = mantissa52;
13165 if guard && (sticky || (result & 1) != 0) {
13166 result += 1;
13167 if result > 0x000FFFFFFFFFFFFF {
13168 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13170 }
13171 }
13172 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13173 }
13174
13175 let shift = msb - 52;
13177
13178 if shift <= 0 {
13179 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13181 let bits = ((biased_exp as u64) << 52) | mantissa;
13182 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13183 }
13184
13185 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13187 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13188 let sticky = if shift > 1 {
13189 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13190 } else { false };
13191
13192 let mut result_mant = mantissa;
13193 let mut result_exp = biased_exp;
13194 if guard && (sticky || (result_mant & 1) != 0) {
13195 result_mant += 1;
13196 if result_mant > 0x000FFFFFFFFFFFFF {
13197 result_mant = 0;
13198 result_exp += 1;
13199 if result_exp >= 2047 {
13200 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13201 }
13202 }
13203 }
13204
13205 let bits = ((result_exp as u64) << 52) | result_mant;
13206 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13207}
13208
13209unsafe fn hex_val(c: u8) -> Option<u8> {
13210 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13211 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13212 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13213 else { None }
13214}
13215
13216#[no_mangle]
13217pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13218 let mut end: *mut u8 = s as *mut u8;
13219 let r = parse_float(s as *const u8, &mut end, false);
13220 if !endptr.is_null() { *endptr = end as *mut c_char; }
13221 r
13222}
13223
13224#[no_mangle]
13225pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13226 let mut end: *mut u8 = s as *mut u8;
13227 let r = parse_float(s as *const u8, &mut end, true);
13228 if !endptr.is_null() { *endptr = end as *mut c_char; }
13229 r as f32
13230}
13231
13232#[no_mangle]
13233#[cfg(target_arch = "x86_64")]
13234pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13235 strtod(s, endptr)
13236}
13237
13238#[no_mangle]
13239#[cfg(target_arch = "aarch64")]
13240pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13241 strtod(s, endptr) as f128
13242}
13243
13244#[no_mangle]
13245#[cfg(target_arch = "riscv64")]
13246pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13247 strtod(s, endptr) as f128
13248}
13249
13250#[no_mangle]
13251pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13252 strtod(s, core::ptr::null_mut())
13253}
13254
13255#[repr(C)]
13260struct MsCookie {
13261 bufp: *mut *mut c_char,
13262 sizep: *mut usize,
13263 pos: usize,
13264 len: usize,
13265 buf: *mut u8,
13266 space: usize,
13267}
13268
13269#[repr(C)]
13270struct MfCookie {
13271 pos: usize,
13272 len: usize,
13273 size: usize,
13274 buf: *mut u8,
13275 mode: c_char,
13276}
13277
13278unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13279 let c = (*f).cookie as *mut MsCookie;
13280 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13281 let base: i64 = match whence {
13282 0 => 0,
13283 1 => (*c).pos as i64,
13284 2 => (*c).len as i64,
13285 _ => { ERRNO = EINVAL; return -1; }
13286 };
13287 if off < -base || off > isize::MAX as i64 - base { ERRNO = EINVAL; return -1; }
13288 (*c).pos = (base + off) as usize;
13289 (*c).pos as i64
13290}
13291
13292unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13293 let c = (*f).cookie as *mut MsCookie;
13294 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13295 if buffered > 0 {
13296 (*f).wpos = (*f).wbase;
13297 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13298 }
13299 if len == 0 { return 0; }
13300 if (*c).pos + len >= (*c).space {
13301 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13302 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13303 if newbuf.is_null() { return 0; }
13304 *(*c).bufp = newbuf as *mut c_char;
13305 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13306 (*c).buf = newbuf;
13307 (*c).space = new_space;
13308 }
13309 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13310 (*c).pos += len;
13311 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13312 *(*c).sizep = (*c).pos;
13313 len
13314}
13315
13316unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13317 0
13318}
13319
13320#[no_mangle]
13321pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13322 if bufp.is_null() || sizep.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13323 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13324 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13325 let buf_area = buf_ptr(f);
13326 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13327 (*f).flags = F_NORD | F_SVB;
13328 (*f).lbf = -1;
13329 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13330 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13331 (*c).bufp = bufp;
13332 (*c).sizep = sizep;
13333 (*c).pos = 0;
13334 (*c).len = 0;
13335 (*c).buf = core::ptr::null_mut();
13336 (*c).space = 0;
13337 (*f).cookie = c as *mut c_void;
13338 (*f).write_fn = Some(ms_write);
13339 (*f).seek_fn = Some(ms_seek);
13340 *bufp = core::ptr::null_mut();
13341 *sizep = 0;
13342 f
13343}
13344
13345unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13346 let c = (*f).cookie as *mut MfCookie;
13347 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13348 let base: i64 = match whence {
13349 0 => 0,
13350 1 => (*c).pos as i64,
13351 2 => (*c).len as i64,
13352 _ => { ERRNO = EINVAL; return -1; }
13353 };
13354 if off < -base || off > (*c).size as i64 - base { ERRNO = EINVAL; return -1; }
13355 (*c).pos = (base + off) as usize;
13356 (*c).pos as i64
13357}
13358
13359unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13360 let c = (*f).cookie as *mut MfCookie;
13361 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13362 let mut l = len;
13363 if l > rem {
13364 l = rem;
13365 (*f).flags |= F_EOF;
13366 }
13367 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13368 (*c).pos += l;
13369 rem -= l;
13370 if rem > (*f).buf_size { rem = (*f).buf_size; }
13371 (*f).rpos = (*f).buf;
13372 (*f).rend = (*f).buf.add(rem);
13373 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13374 (*c).pos += rem;
13375 l
13376}
13377
13378unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13379 let c = (*f).cookie as *mut MfCookie;
13380 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13381 if buffered > 0 {
13382 (*f).wpos = (*f).wbase;
13383 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13384 }
13385 if len == 0 { return 0; }
13386 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13387 let rem = (*c).size - (*c).pos;
13388 let mut l = len;
13389 if l > rem { l = rem; }
13390 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13391 (*c).pos += l;
13392 if (*c).pos > (*c).len {
13393 (*c).len = (*c).pos;
13394 if (*c).len < (*c).size {
13395 *(*c).buf.add((*c).len) = 0;
13396 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13397 *(*c).buf.add((*c).size - 1) = 0;
13398 }
13399 }
13400 l
13401}
13402
13403unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13404 0
13405}
13406
13407#[no_mangle]
13408pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13409 if mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13410 let m = *mode;
13411 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13412 ERRNO = EINVAL; return core::ptr::null_mut();
13413 }
13414 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13415 let need_alloc = buf.is_null();
13416 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13417 let f = calloc(1, alloc_size) as *mut FILE;
13418 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13419 let buf_area = buf_ptr(f);
13420 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13421 (*f).flags |= F_SVB;
13422 let actual_buf: *mut u8 = if need_alloc {
13423 (f as *mut u8).add(alloc_size - size)
13424 } else {
13425 buf as *mut u8
13426 };
13427 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13428 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13429 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13430 (*c).buf = actual_buf;
13431 (*c).size = size;
13432 (*c).mode = m;
13433 (*f).cookie = c as *mut c_void;
13434 (*f).read_fn = Some(mread);
13435 (*f).write_fn = Some(mwrite);
13436 (*f).seek_fn = Some(mseek);
13437 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13438 if m == b'r' as c_char {
13439 (*c).len = size;
13440 } else if m == b'a' as c_char {
13441 (*c).len = strnlen(actual_buf, size);
13442 (*c).pos = (*c).len;
13443 } else if has_plus {
13444 *actual_buf = 0;
13445 }
13446 f
13447}
13448
13449#[repr(C)]
13454struct kernel_stat64 {
13455 st_dev: u64,
13456 st_ino: u64,
13457 st_nlink: u64,
13458 st_mode: u32,
13459 st_uid: u32,
13460 st_gid: u32,
13461 __pad0: c_int,
13462 st_rdev: u64,
13463 st_size: i64,
13464 st_blksize: i64,
13465 st_blocks: i64,
13466 st_atime: i64,
13467 st_atime_nsec: i64,
13468 st_mtime: i64,
13469 st_mtime_nsec: i64,
13470 st_ctime: i64,
13471 st_ctime_nsec: i64,
13472 __unused: [i64; 3],
13473}
13474
13475#[inline]
13477unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
13478 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
13479}
13480
13481const HSEARCH_MINSIZE: usize = 8;
13486
13487#[repr(C)]
13488#[derive(Copy, Clone)]
13489pub struct HSearchEntry {
13490 key: *mut c_char,
13491 data: *mut c_void,
13492}
13493
13494#[repr(C)]
13495struct HTab {
13496 entries: *mut HSearchEntry,
13497 mask: usize,
13498 used: usize,
13499}
13500
13501#[repr(C)]
13502pub struct HSearchData {
13503 tab: *mut HTab,
13504 __unused1: c_uint,
13505 __unused2: c_uint,
13506}
13507
13508static mut HTAB_DATA: HSearchData = HSearchData {
13510 tab: core::ptr::null_mut(),
13511 __unused1: 0,
13512 __unused2: 0,
13513};
13514
13515unsafe fn keyhash(k: *const c_char) -> usize {
13516 let mut h: usize = 0;
13517 let mut p = k;
13518 while *p != 0 {
13519 h = h.wrapping_mul(31).wrapping_add(*p as usize);
13520 p = p.add(1);
13521 }
13522 h
13523}
13524
13525unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
13526 let tab = (*htab).tab;
13527 let mask = (*tab).mask;
13528 let entries = (*tab).entries;
13529 let mut i = hash;
13530 let mut j: usize = 1;
13531 loop {
13532 let e = entries.add(i & mask);
13533 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
13534 return e;
13535 }
13536 i = i.wrapping_add(j);
13537 j += 1;
13538 }
13539}
13540
13541unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
13542 let tab = (*htab).tab;
13543 let old_entries = (*tab).entries;
13544 let old_size = (*tab).mask + 1;
13545
13546 let mut newsize: usize = HSEARCH_MINSIZE;
13547 while newsize < nel {
13548 let Some(next) = newsize.checked_mul(2) else {
13549 ERRNO = ENOMEM;
13550 return 0;
13551 };
13552 newsize = next;
13553 }
13554
13555 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
13556 if new_entries.is_null() {
13557 ERRNO = ENOMEM;
13558 return 0;
13559 }
13560 (*tab).entries = new_entries;
13561 (*tab).mask = newsize - 1;
13562
13563 if !old_entries.is_null() {
13564 for idx in 0..old_size {
13565 let old_e = old_entries.add(idx);
13566 if !(*old_e).key.is_null() {
13567 let h = keyhash((*old_e).key);
13568 let mut i = h;
13569 let mut j: usize = 1;
13570 loop {
13571 let e = new_entries.add(i & (*tab).mask);
13572 if (*e).key.is_null() {
13573 *e = *old_e;
13574 break;
13575 }
13576 i = i.wrapping_add(j);
13577 j += 1;
13578 }
13579 }
13580 }
13581 free(old_entries as *mut c_void);
13582 }
13583 1
13584}
13585
13586unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
13587 if nel == 0 || nel > (1usize << 30) {
13588 ERRNO = ENOMEM;
13589 return 0;
13590 }
13591 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
13592 if (*htab).tab.is_null() {
13593 ERRNO = ENOMEM;
13594 return 0;
13595 }
13596 if htab_resize(nel, htab) == 0 {
13597 free((*htab).tab as *mut c_void);
13598 (*htab).tab = core::ptr::null_mut();
13599 return 0;
13600 }
13601 1
13602}
13603
13604unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
13605 if !(*htab).tab.is_null() {
13606 if !(*(*htab).tab).entries.is_null() {
13607 free((*(*htab).tab).entries as *mut c_void);
13608 }
13609 free((*htab).tab as *mut c_void);
13610 (*htab).tab = core::ptr::null_mut();
13611 }
13612}
13613
13614unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13615 let hash = keyhash(item.key);
13616 let e = htab_lookup(item.key, hash, htab);
13617
13618 if !(*e).key.is_null() {
13619 *retval = e;
13620 return 1;
13621 }
13622 if action == 0 { *retval = core::ptr::null_mut();
13624 return 0;
13625 }
13626 let item_key = item.key;
13628 *e = item;
13629 (*(*htab).tab).used += 1;
13630 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
13631 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
13632 (*(*htab).tab).used -= 1;
13633 (*e).key = core::ptr::null_mut();
13634 *retval = core::ptr::null_mut();
13635 return 0;
13636 }
13637 let e2 = htab_lookup(item_key, hash, htab);
13638 *retval = e2;
13639 return 1;
13640 }
13641 *retval = e;
13642 1
13643}
13644
13645#[no_mangle]
13646pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
13647 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
13648}
13649
13650#[no_mangle]
13651pub unsafe extern "C" fn hdestroy() {
13652 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
13653}
13654
13655#[no_mangle]
13656pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
13657 let mut e: *mut HSearchEntry = core::ptr::null_mut();
13658 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
13659 e
13660}
13661
13662#[no_mangle]
13663pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
13664 hcreate_r_impl(nel, htab)
13665}
13666
13667#[no_mangle]
13668pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
13669 hdestroy_r_impl(htab);
13670}
13671
13672#[no_mangle]
13673pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13674 hsearch_r_impl(item, action, retval, htab)
13675}
13676
13677#[repr(C)]
13682struct QueNode {
13683 next: *mut QueNode,
13684 prev: *mut QueNode,
13685}
13686
13687#[no_mangle]
13688pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
13689 let e = element as *mut QueNode;
13690 let p = pred as *mut QueNode;
13691 if p.is_null() {
13692 (*e).next = core::ptr::null_mut();
13693 (*e).prev = core::ptr::null_mut();
13694 return;
13695 }
13696 (*e).next = (*p).next;
13697 (*e).prev = p;
13698 (*p).next = e;
13699 if !(*e).next.is_null() {
13700 (*(*e).next).prev = e;
13701 }
13702}
13703
13704#[no_mangle]
13705pub unsafe extern "C" fn remque(element: *mut c_void) {
13706 let e = element as *mut QueNode;
13707 if !(*e).next.is_null() {
13708 (*(*e).next).prev = (*e).prev;
13709 }
13710 if !(*e).prev.is_null() {
13711 (*(*e).prev).next = (*e).next;
13712 }
13713}
13714
13715#[no_mangle]
13720pub unsafe extern "C" fn lsearch(
13721 key: *const c_void,
13722 base: *mut c_void,
13723 nelp: *mut usize,
13724 width: usize,
13725 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13726) -> *mut c_void {
13727 let n = *nelp;
13728 let p = base as *mut u8;
13729 for i in 0..n {
13730 let elem = p.add(i * width);
13731 if compar.unwrap()(key, elem as *const c_void) == 0 {
13732 return elem as *mut c_void;
13733 }
13734 }
13735 let dest = p.add(n * width);
13736 memcpy(dest as *mut c_void, key as *const c_void, width);
13737 *nelp = n + 1;
13738 dest as *mut c_void
13739}
13740
13741#[no_mangle]
13742pub unsafe extern "C" fn lfind(
13743 key: *const c_void,
13744 base: *const c_void,
13745 nelp: *mut usize,
13746 width: usize,
13747 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13748) -> *mut c_void {
13749 let n = *nelp;
13750 let p = base as *const u8;
13751 for i in 0..n {
13752 let elem = p.add(i * width);
13753 if compar.unwrap()(key, elem as *const c_void) == 0 {
13754 return elem as *mut c_void;
13755 }
13756 }
13757 core::ptr::null_mut()
13758}
13759
13760#[repr(C)]
13766pub struct TreeNode {
13767 key: *const c_void,
13768 left: *mut TreeNode,
13769 right: *mut TreeNode,
13770}
13771
13772type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
13773
13774unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
13775 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
13776 if !n.is_null() {
13777 (*n).key = key;
13778 (*n).left = core::ptr::null_mut();
13779 (*n).right = core::ptr::null_mut();
13780 }
13781 n
13782}
13783
13784#[no_mangle]
13785pub unsafe extern "C" fn tsearch(
13786 key: *const c_void,
13787 rootp: *mut *mut TreeNode,
13788 compar: ComparFn,
13789) -> *mut c_void {
13790 if rootp.is_null() {
13791 return core::ptr::null_mut();
13792 }
13793 let mut pp = rootp;
13794 loop {
13795 let n = *pp;
13796 if n.is_null() {
13797 let r = bst_new(key);
13798 if r.is_null() {
13799 return core::ptr::null_mut();
13800 }
13801 *pp = r;
13802 return r as *mut c_void;
13803 }
13804 let c = compar.unwrap()(key, (*n).key);
13805 if c == 0 {
13806 return n as *mut c_void;
13807 }
13808 if c < 0 {
13809 pp = &mut (*n).left;
13810 } else {
13811 pp = &mut (*n).right;
13812 }
13813 }
13814}
13815
13816#[no_mangle]
13817pub unsafe extern "C" fn tfind(
13818 key: *const c_void,
13819 rootp: *const *mut TreeNode,
13820 compar: ComparFn,
13821) -> *mut c_void {
13822 if rootp.is_null() {
13823 return core::ptr::null_mut();
13824 }
13825 let mut n = *rootp;
13826 loop {
13827 if n.is_null() {
13828 return core::ptr::null_mut();
13829 }
13830 let c = compar.unwrap()(key, (*n).key);
13831 if c == 0 {
13832 return n as *mut c_void;
13833 }
13834 if c < 0 {
13835 n = (*n).left;
13836 } else {
13837 n = (*n).right;
13838 }
13839 }
13840}
13841
13842#[no_mangle]
13843pub unsafe extern "C" fn tdelete(
13844 key: *const c_void,
13845 rootp: *mut *mut TreeNode,
13846 compar: ComparFn,
13847) -> *mut c_void {
13848 if rootp.is_null() {
13849 return core::ptr::null_mut();
13850 }
13851 let mut pp = rootp;
13852 loop {
13853 let n = *pp;
13854 if n.is_null() {
13855 return core::ptr::null_mut();
13856 }
13857 let c = compar.unwrap()(key, (*n).key);
13858 if c == 0 {
13859 break;
13860 }
13861 if c < 0 {
13862 pp = &mut (*n).left;
13863 } else {
13864 pp = &mut (*n).right;
13865 }
13866 }
13867 let n = *pp;
13868 let parent = *rootp;
13870 if !(*n).left.is_null() {
13871 let mut q = &mut (*n).left;
13873 while !(*(*q)).right.is_null() {
13874 q = &mut (*(*q)).right;
13875 }
13876 let pred = *q;
13877 (*n).key = (*pred).key;
13879 *q = (*pred).left;
13881 free(pred as *mut c_void);
13882 } else {
13883 *pp = (*n).right;
13885 free(n as *mut c_void);
13886 }
13887 parent as *mut c_void
13888}
13889
13890#[no_mangle]
13891pub unsafe extern "C" fn twalk(
13892 root: *const TreeNode,
13893 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
13894) {
13895 unsafe fn walk(
13896 node: *const TreeNode,
13897 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
13898 depth: c_int,
13899 ) {
13900 if node.is_null() {
13901 return;
13902 }
13903 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
13904 if is_leaf {
13905 action.unwrap()(node as *const c_void, 3, depth); } else {
13907 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
13909 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
13911 action.unwrap()(node as *const c_void, 2, depth); }
13913 }
13914 walk(root, action, 0);
13915}
13916
13917#[no_mangle]
13918pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
13919 if root.is_null() {
13920 return;
13921 }
13922 tdestroy((*root).left, freekey);
13923 tdestroy((*root).right, freekey);
13924 if let Some(f) = freekey {
13925 f((*root).key as *mut c_void);
13926 }
13927 free(root as *mut c_void);
13928}
13929
13930const FNM_PATHNAME: c_int = 0x1;
13935const FNM_NOESCAPE: c_int = 0x2;
13936const FNM_PERIOD: c_int = 0x4;
13937const FNM_LEADING_DIR: c_int = 0x8;
13938const FNM_CASEFOLD: c_int = 0x10;
13939const FNM_NOMATCH: c_int = 1;
13940
13941const FNM_END: c_int = 0;
13942const FNM_STAR: c_int = -5;
13943const FNM_QUESTION: c_int = -4;
13944const FNM_BRACKET: c_int = -3;
13945const FNM_UNMATCHABLE: c_int = -2;
13946
13947fn ascii_tolower(c: u8) -> u8 {
13948 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
13949}
13950
13951fn ascii_toupper(c: u8) -> u8 {
13952 if c >= b'a' && c <= b'z' { c - 32 } else { c }
13953}
13954
13955fn ascii_casefold(k: u8) -> u8 {
13956 let upper = ascii_toupper(k);
13957 if upper != k { upper } else { ascii_tolower(k) }
13958}
13959
13960unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
13963 if m == 0 || *pat == 0 {
13964 return (FNM_END, 0);
13965 }
13966 let mut p = pat;
13967 let mut step = 1usize;
13968 let mut esc = false;
13969 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
13970 p = p.add(1);
13971 step = 2;
13972 esc = true;
13973 }
13974 if *p == b'[' && !esc {
13975 let mut k = 1usize;
13977 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
13978 if k < m && *pat.add(k) == b']' { k += 1; }
13979 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
13980 if k + 1 < m && *pat.add(k) == b'[' &&
13981 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
13982 let z = *pat.add(k+1);
13983 k += 2;
13984 if k < m { k += 1; }
13985 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
13986 if k == m || *pat.add(k) == 0 { break; }
13987 }
13988 k += 1;
13989 }
13990 if k == m || *pat.add(k) == 0 {
13991 return (b'[' as c_int, 1);
13993 }
13994 return (FNM_BRACKET, k + 1);
13995 }
13996 if *p == b'*' && !esc {
13997 return (FNM_STAR, 1);
13998 }
13999 if *p == b'?' && !esc {
14000 return (FNM_QUESTION, 1);
14001 }
14002 (*p as c_int, step)
14003}
14004
14005unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14006 let eq = |c: u8| k == c || kfold == c;
14007 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14008 match name {
14009 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14010 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14011 b"blank" => eq(b' ') || eq(b'\t'),
14012 b"cntrl" => k < 0x20 || k == 0x7f,
14013 b"digit" => in_range(b'0', b'9'),
14014 b"graph" => k >= 0x21 && k <= 0x7e,
14015 b"lower" => in_range(b'a', b'z'),
14016 b"print" => k >= 0x20 && k <= 0x7e,
14017 b"punct" =>
14018 (k >= 0x21 && k <= 0x2f) ||
14019 (k >= 0x3a && k <= 0x40) ||
14020 (k >= 0x5b && k <= 0x60) ||
14021 (k >= 0x7b && k <= 0x7e),
14022 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14023 b"upper" => in_range(b'A', b'Z'),
14024 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14025 _ => false,
14026 }
14027}
14028
14029unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14031 let mut inv = false;
14032 p = p.add(1); if *p == b'^' || *p == b'!' {
14034 inv = true;
14035 p = p.add(1);
14036 }
14037 if *p == b']' {
14039 if k == b']' { return !inv; }
14040 p = p.add(1);
14041 } else if *p == b'-' {
14042 if k == b'-' { return !inv; }
14043 p = p.add(1);
14044 }
14045 while *p != b']' && *p != 0 {
14046 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14047 let lo = *p.sub(1);
14049 let hi = *p.add(1);
14050 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14051 return !inv;
14052 }
14053 p = p.add(2);
14054 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14055 let z = *p.add(1);
14056 let start = p.add(2);
14057 let mut q = start;
14058 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14059 if *q != 0 {
14060 let len = (q as usize) - (start as usize);
14061 if len > 0 {
14062 let inner = core::slice::from_raw_parts(start, len);
14063 let matched =
14064 if z == b':' { match_class(inner, k, kfold) }
14065 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14066 if matched { return !inv; }
14067 }
14068 p = q.add(2);
14069 continue;
14070 }
14071 } else {
14072 if *p == k || *p == kfold {
14073 return !inv;
14074 }
14075 p = p.add(1);
14076 }
14077 }
14078 inv
14079}
14080
14081unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14083 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14085 return FNM_NOMATCH;
14086 }
14087
14088 let mut p = pat;
14089 let mut s = str;
14090
14091 loop {
14093 let (tok, step) = pat_next(p, usize::MAX, flags);
14094 match tok {
14095 FNM_END => {
14096 return if *s == 0 { 0 } else { FNM_NOMATCH };
14097 }
14098 FNM_STAR => {
14099 p = p.add(1);
14100 break;
14101 }
14102 FNM_QUESTION => {
14103 if *s == 0 { return FNM_NOMATCH; }
14104 s = s.add(1);
14105 p = p.add(step);
14106 }
14107 FNM_BRACKET => {
14108 if *s == 0 { return FNM_NOMATCH; }
14109 let k = *s;
14110 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14111 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14112 p = p.add(step);
14113 s = s.add(1);
14114 }
14115 c => {
14116 if *s == 0 { return FNM_NOMATCH; }
14117 let k = *s;
14118 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14119 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14120 p = p.add(step);
14121 s = s.add(1);
14122 }
14123 }
14124 }
14125
14126 let mut ptail = p;
14129 let mut tailcnt: usize = 0;
14130 let mut pp = p;
14131 loop {
14132 let (tok, step) = pat_next(pp, usize::MAX, flags);
14133 if tok == FNM_END { break; }
14134 if tok == FNM_STAR {
14135 tailcnt = 0;
14136 ptail = pp.add(1);
14137 } else {
14138 tailcnt += 1;
14139 }
14140 pp = pp.add(step);
14141 }
14142
14143 let slen = strlen(s as *const c_char);
14145 if slen < tailcnt { return FNM_NOMATCH; }
14146
14147 let stail = s.add(slen - tailcnt);
14149 let mut tp = ptail;
14150 let mut ts = stail;
14151 loop {
14152 let (tok, step) = pat_next(tp, usize::MAX, flags);
14153 tp = tp.add(step);
14154 if tok == FNM_END {
14155 break;
14156 }
14157 let k = *ts;
14158 if k == 0 { return FNM_NOMATCH; }
14159 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14160 match tok {
14161 FNM_QUESTION => { ts = ts.add(1); }
14162 FNM_BRACKET => {
14163 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14164 ts = ts.add(1);
14165 }
14166 c => {
14167 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14168 ts = ts.add(1);
14169 }
14170 }
14171 }
14172
14173 let endstr = stail;
14174 let endpat = ptail;
14175
14176 let mut cp = p;
14177 let mut cs = s;
14178 while cp < endpat {
14179 let (tok, step) = pat_next(cp, usize::MAX, flags);
14180 if tok == FNM_STAR {
14181 cp = cp.add(step);
14182 cs = s;
14183 continue;
14184 }
14185 let comp_start = cp;
14186 let mut ok = false;
14187 let mut try_s = cs;
14188 while try_s < endstr {
14189 let mut tmp_p = comp_start;
14190 let mut tmp_s = try_s;
14191 let mut matched = true;
14192 loop {
14193 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14194 if t == FNM_STAR || t == FNM_END {
14195 cp = tmp_p;
14196 cs = tmp_s;
14197 ok = true;
14198 break;
14199 }
14200 if *tmp_s == 0 {
14201 matched = false;
14202 break;
14203 }
14204 let k = *tmp_s;
14205 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14206 match t {
14207 FNM_QUESTION => {
14208 tmp_s = tmp_s.add(1);
14209 }
14210 FNM_BRACKET => {
14211 if !match_bracket(tmp_p, k, kfold) {
14212 matched = false;
14213 break;
14214 }
14215 tmp_s = tmp_s.add(1);
14216 }
14217 c => {
14218 if k as c_int != c && kfold as c_int != c {
14219 matched = false;
14220 break;
14221 }
14222 tmp_s = tmp_s.add(1);
14223 }
14224 }
14225 tmp_p = tmp_p.add(st);
14226 }
14227 if ok { break; }
14228 if !matched {
14229 try_s = try_s.add(1);
14230 }
14231 }
14232 if !ok {
14233 return FNM_NOMATCH;
14234 }
14235 }
14236 0
14237}
14238
14239#[no_mangle]
14240pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14241 let pat = pat as *const u8;
14242 let str = str as *const u8;
14243
14244 if flags & FNM_PATHNAME != 0 {
14245 let mut s = str;
14247 let mut p = pat;
14248 loop {
14249 let mut send = s;
14251 while *send != 0 && *send != b'/' { send = send.add(1); }
14252 let mut pend = p;
14254 loop {
14255 let (tok, step) = pat_next(pend, usize::MAX, flags);
14256 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14257 break;
14258 }
14259 pend = pend.add(step);
14260 }
14261 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14262 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14263 let str_is_slash = *send == b'/';
14264 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14265 return FNM_NOMATCH;
14266 }
14267 let plen = (pend as usize) - (p as usize);
14270 let slen = (send as usize) - (s as usize);
14271 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14274 let mut pbuf = [0u8; 1025];
14275 let mut sbuf = [0u8; 1025];
14276 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14277 pbuf[plen] = 0;
14278 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14279 sbuf[slen] = 0;
14280 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14281 return FNM_NOMATCH;
14282 }
14283 if !pat_is_slash {
14284 return 0;
14285 }
14286 s = send.add(1);
14287 p = pend.add(pstep);
14288 }
14289 }
14290
14291 if flags & FNM_LEADING_DIR != 0 {
14292 let mut s = str;
14294 while *s != 0 {
14295 if *s == b'/' {
14296 let len = (s as usize) - (str as usize);
14299 if len < 4096 {
14301 let mut buf = [0u8; 4096];
14302 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14303 buf[len] = 0;
14304 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14305 return 0;
14306 }
14307 }
14308 }
14309 s = s.add(1);
14310 }
14311 }
14312
14313 fnmatch_internal(pat, str, flags)
14314}
14315
14316#[no_mangle]
14321pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14322 fopen(name, mode)
14323}
14324
14325#[no_mangle]
14326pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14327 if !f.is_null() {
14328 fclose(f);
14329 }
14330 1
14331}
14332
14333static mut MNTENT_MNT: MntEnt = MntEnt {
14335 mnt_fsname: core::ptr::null_mut(),
14336 mnt_dir: core::ptr::null_mut(),
14337 mnt_type: core::ptr::null_mut(),
14338 mnt_opts: core::ptr::null_mut(),
14339 mnt_freq: 0,
14340 mnt_passno: 0,
14341};
14342
14343#[repr(C)]
14344pub struct MntEnt {
14345 mnt_fsname: *mut c_char,
14346 mnt_dir: *mut c_char,
14347 mnt_type: *mut c_char,
14348 mnt_opts: *mut c_char,
14349 mnt_freq: c_int,
14350 mnt_passno: c_int,
14351}
14352
14353unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14354 let mut dest = beg;
14355 let mut src = beg;
14356 while *src != 0 {
14357 if *src != b'\\' as c_char {
14358 *dest = *src;
14359 dest = dest.add(1);
14360 src = src.add(1);
14361 continue;
14362 }
14363 if *src.add(1) == b'\\' as c_char {
14365 src = src.add(1);
14366 *dest = *src;
14367 dest = dest.add(1);
14368 src = src.add(1);
14369 continue;
14370 }
14371 let mut val: u8 = 0;
14373 let mut cnt = 0;
14374 let mut sp = src.add(1);
14375 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14376 val = val * 8 + (*sp as u8 - b'0');
14377 sp = sp.add(1);
14378 cnt += 1;
14379 }
14380 if cnt > 0 {
14381 *dest = val as c_char;
14382 dest = dest.add(1);
14383 src = sp;
14384 } else {
14385 *dest = *src;
14386 dest = dest.add(1);
14387 src = src.add(1);
14388 }
14389 }
14390 *dest = 0;
14391 beg
14392}
14393
14394unsafe fn parse_mntent_line(
14395 linebuf: *mut c_char,
14396 mnt: *mut MntEnt,
14397) -> *mut MntEnt {
14398 let _len = strlen(linebuf as *const c_char);
14399 let mut p = linebuf;
14402 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14404 p = p.add(1);
14405 }
14406 if *p == 0 || *p == b'#' as c_char {
14407 return core::ptr::null_mut();
14408 }
14409
14410 (*mnt).mnt_fsname = p;
14412 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14413 p = p.add(1);
14414 }
14415 if *p == 0 { return core::ptr::null_mut(); }
14416 *p = 0;
14417 p = p.add(1);
14418 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14419
14420 (*mnt).mnt_dir = p;
14422 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14423 p = p.add(1);
14424 }
14425 if *p == 0 { return core::ptr::null_mut(); }
14426 *p = 0;
14427 p = p.add(1);
14428 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14429
14430 (*mnt).mnt_type = p;
14432 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14433 p = p.add(1);
14434 }
14435 if *p == 0 { return core::ptr::null_mut(); }
14436 *p = 0;
14437 p = p.add(1);
14438 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14439
14440 (*mnt).mnt_opts = p;
14442 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14443 p = p.add(1);
14444 }
14445 if *p != 0 {
14446 *p = 0;
14447 p = p.add(1);
14448 }
14449 if *(*mnt).mnt_opts == 0 {
14450 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
14451 }
14452
14453 (*mnt).mnt_freq = 0;
14455 (*mnt).mnt_passno = 0;
14456 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14458 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14459 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
14460 p = p.add(1);
14461 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14462 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
14463 p = p.add(1);
14464 }
14465 }
14466 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14467 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14468 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
14469 p = p.add(1);
14470 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14471 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
14472 p = p.add(1);
14473 }
14474 }
14475
14476 unescape_ent((*mnt).mnt_fsname);
14478 unescape_ent((*mnt).mnt_dir);
14479 unescape_ent((*mnt).mnt_type);
14480 unescape_ent((*mnt).mnt_opts);
14481
14482 mnt
14483}
14484
14485static SENTINEL_PTR: usize = 1;
14488
14489unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
14491 fgetc(f)
14492}
14493
14494unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
14495 if n == 0 { return core::ptr::null_mut(); }
14496 let max = n - 1;
14497 let mut i = 0usize;
14498 while i < max {
14499 let c = mntent_fgetc(f);
14500 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
14501 *buf.add(i) = c as c_char;
14502 i += 1;
14503 if c == b'\n' as c_int { break; }
14504 }
14505 *buf.add(i) = 0;
14506 buf
14507}
14508
14509#[no_mangle]
14510pub unsafe extern "C" fn getmntent_r(
14511 f: *mut FILE,
14512 mnt: *mut MntEnt,
14513 mut linebuf: *mut c_char,
14514 _buflen: c_int,
14515) -> *mut MntEnt {
14516 let use_internal = linebuf as usize == SENTINEL_PTR;
14517
14518 (*mnt).mnt_freq = 0;
14519 (*mnt).mnt_passno = 0;
14520
14521 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
14523
14524 loop {
14525 if use_internal {
14526 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
14527 }
14528 let res = mntent_fgets(linebuf, 4096, f);
14529 if res.is_null() {
14530 return core::ptr::null_mut();
14531 }
14532 let mut has_newline = false;
14533 let mut p = linebuf;
14534 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
14535 if !has_newline {
14536 ERRNO = 34;
14537 return core::ptr::null_mut();
14538 }
14539 let result = parse_mntent_line(linebuf, mnt);
14540 if !result.is_null() {
14541 return result;
14542 }
14543 }
14544}
14545
14546#[no_mangle]
14547pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
14548 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
14549}
14550
14551#[no_mangle]
14552pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
14553 fseek(f, 0, 2); let written = fprintf(
14555 f,
14556 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
14557 (*mnt).mnt_fsname,
14558 (*mnt).mnt_dir,
14559 (*mnt).mnt_type,
14560 (*mnt).mnt_opts,
14561 (*mnt).mnt_freq,
14562 (*mnt).mnt_passno,
14563 );
14564 if written < 0 { 1 } else { 0 }
14565}
14566
14567#[no_mangle]
14568pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
14569 let l = strlen(opt as *const c_char);
14570 let mut p = (*mnt).mnt_opts;
14571 loop {
14572 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
14573 let after = *p.add(l);
14574 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
14575 return p;
14576 }
14577 }
14578 let comma = strchr(p as *const u8, b',' as c_int);
14579 if comma.is_null() {
14580 return core::ptr::null_mut();
14581 }
14582 p = comma.add(1) as *mut c_char;
14583 }
14584}
14585
14586const EEXIST: c_int = 17;
14594const ENAMETOOLONG: c_int = 36;
14595const EMFILE: c_int = 24;
14596const EIDRM: c_int = 43;
14597
14598#[inline]
14599unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
14600 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
14601}
14602
14603#[inline]
14604unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
14605 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
14606}
14607
14608#[inline]
14609unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
14610 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
14611}
14612
14613#[inline]
14614unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14615 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
14616}
14617
14618#[inline]
14619unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
14620 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
14621}
14622
14623#[inline]
14624unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
14625 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
14626}
14627
14628#[inline]
14629unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
14630 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
14631}
14632
14633#[inline]
14634unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
14635 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
14636}
14637
14638#[inline]
14639unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
14640 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
14641}
14642
14643#[inline]
14644unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
14645 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
14646}
14647
14648#[inline]
14649unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14650 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
14651}
14652
14653#[no_mangle]
14655pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
14656 let mut st: kernel_stat64 = core::mem::zeroed();
14657 let r = sys_stat(path as *const u8, &mut st);
14658 if r < 0 {
14659 ERRNO = (-r) as c_int;
14660 return -1;
14661 }
14662 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
14663}
14664
14665#[no_mangle]
14667pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
14668 let r = sys_msgget(key, msgflg);
14669 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14670}
14671
14672#[no_mangle]
14674pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
14675 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
14676 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14677}
14678
14679#[no_mangle]
14681pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
14682 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
14683 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
14684}
14685
14686#[no_mangle]
14688pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14689 let r = sys_msgctl(msqid, cmd, buf);
14690 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14691}
14692
14693#[no_mangle]
14695pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
14696 if nsems > 65535 { ERRNO = 22; return -1; }
14697 let r = sys_semget(key, nsems, semflg);
14698 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14699}
14700
14701#[no_mangle]
14703pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
14704 let r = sys_semop(semid, sops, nsops);
14705 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14706}
14707
14708#[no_mangle]
14710pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
14711 let mut arg: *mut c_void = core::ptr::null_mut();
14712 match cmd {
14714 16 | 13 | 17 | 1 | 3 | 2 | 0x102 | 0x104 | 0x106 => {
14715 arg = args.next_arg::<*mut c_void>();
14716 }
14717 _ => {}
14718 }
14719 let r = sys_semctl(semid, semnum, cmd, arg);
14720 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14721}
14722
14723#[no_mangle]
14725pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
14726 let r = sys_shmget(key, size, shmflg);
14727 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14728}
14729
14730#[no_mangle]
14732pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
14733 let r = sys_shmat(shmid, shmaddr, shmflg);
14734 if (r as usize) > (-(4096isize as isize)) as usize {
14735 ERRNO = (-r) as c_int;
14736 return core::ptr::null_mut();
14737 }
14738 r as *mut c_void
14739}
14740
14741#[no_mangle]
14743pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
14744 let r = sys_shmdt(shmaddr);
14745 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14746}
14747
14748#[no_mangle]
14750pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14751 let r = sys_shmctl(shmid, cmd, buf);
14752 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14753}
14754
14755#[no_mangle]
14765pub static mut __auxv: *const usize = core::ptr::null();
14766
14767#[no_mangle]
14768pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
14769 let mut p = __auxv;
14770 if p.is_null() {
14771 return 0;
14772 }
14773 loop {
14774 let tag = *p;
14775 if tag == 0 {
14776 return 0;
14777 }
14778 if tag == type_ as usize {
14779 return *p.add(1) as c_ulong;
14780 }
14781 p = p.add(2);
14782 }
14783}
14784
14785type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
14786type InitFn = unsafe extern "C" fn();
14787
14788#[no_mangle]
14789pub unsafe extern "C" fn __libc_start_main(
14790 main: MainFn,
14791 argc: c_int,
14792 argv: *const *const c_char,
14793 _init: *const c_void,
14794 _fini: *const c_void,
14795 _rtld_fini: *const c_void,
14796 _stack_end: *const c_void,
14797) -> ! {
14798 let envp = argv.add((argc + 1) as usize);
14799 __environ = envp as *mut *mut c_char;
14800 environ = __environ; __stdio_init();
14802
14803 let mut set: SigSetT = 0;
14804 sigemptyset(&mut set);
14805 sigaddset(&mut set, SIGCANCEL);
14806 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
14807
14808 if !_init.is_null() {
14809 let init_fn: InitFn = core::mem::transmute(_init);
14810 init_fn();
14811 }
14812
14813 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
14817 {
14818 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
14820 let a = core::ptr::read_unaligned(random_ptr as *const u64);
14821 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
14822 __stack_chk_guard = (a ^ b) as usize;
14823 } else {
14824 __stack_chk_guard = 0xdefaced_cafebeef;
14826 }
14827 }
14828
14829 let result = main(argc, argv, envp);
14830
14831 if !_fini.is_null() {
14832 let fini_fn: InitFn = core::mem::transmute(_fini);
14833 fini_fn();
14834 }
14835
14836 exit(result);
14837}
14838
14839type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
14840type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
14841type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
14842type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
14843
14844static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
14845static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
14846static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
14847static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
14848
14849#[no_mangle]
14850pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
14851 LDSO_DLOPEN = Some(f);
14852}
14853
14854#[no_mangle]
14855pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
14856 LDSO_DLSYM = Some(f);
14857}
14858
14859#[no_mangle]
14860pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
14861 LDSO_DLCLOSE = Some(f);
14862}
14863
14864#[no_mangle]
14865pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
14866 LDSO_DLERROR = Some(f);
14867}
14868
14869#[no_mangle]
14870pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
14871 if let Some(f) = LDSO_DLOPEN {
14872 f(filename, flags)
14873 } else {
14874 null_mut()
14875 }
14876}
14877
14878#[no_mangle]
14879pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
14880 if let Some(f) = LDSO_DLSYM {
14881 f(handle, symbol)
14882 } else {
14883 null_mut()
14884 }
14885}
14886
14887#[no_mangle]
14888pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
14889 if let Some(f) = LDSO_DLCLOSE {
14890 f(handle)
14891 } else {
14892 0
14893 }
14894}
14895
14896#[no_mangle]
14897pub unsafe extern "C" fn dlerror() -> *const c_char {
14898 if let Some(f) = LDSO_DLERROR {
14899 f()
14900 } else {
14901 core::ptr::null()
14902 }
14903}
14904
14905include!("crypt_impl.rs");
14906include!("statvfs.rs");
14907include!("daemon.rs");
14908include!("dn_expand.rs");
14909include!("lrand48.rs");
14910include!("strverscmp.rs");
14911include!("syscall.rs");
14912include!("pthread_atfork.rs");
14913include!("fenv.rs");
14914include!("locale_ctype.rs");
14915include!("regression_stubs.rs");
14916
14917type regoff_t = c_int;
14922
14923#[repr(C)]
14924pub struct regex_t {
14925 pub re_nsub: usize,
14926 pub __opaque: *mut c_void,
14927 pub __padding: [*mut c_void; 4],
14928 pub __nsub2: usize,
14929 pub __padding2: c_char,
14930}
14931
14932#[repr(C)]
14933pub struct regmatch_t {
14934 pub rm_so: regoff_t,
14935 pub rm_eo: regoff_t,
14936}
14937
14938include!("regex.rs");
14939
14940#[cfg(test)]
14941mod libc_unit_stub {
14942 #[test]
14943 fn stub() {
14944 assert!(true);
14945 }
14946}