1#[repr(C)]
8#[derive(Copy, Clone)]
9pub struct CookieIo {
10 pub read: usize,
11 pub write: usize,
12 pub seek: usize,
13 pub close: usize,
14}
15
16#[repr(C)]
17struct CookieFile {
18 cookie: *mut c_void,
19 io: CookieIo,
20}
21
22type CookieReadFn = unsafe extern "C" fn(*mut c_void, *mut c_char, usize) -> isize;
23type CookieWriteFn = unsafe extern "C" fn(*mut c_void, *const c_char, usize) -> isize;
24type CookieSeekFn = unsafe extern "C" fn(*mut c_void, *mut i64, c_int) -> c_int;
25type CookieCloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
26
27unsafe extern "C" fn cookie_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
28 let cf = (*f).cookie as *mut CookieFile;
29 if cf.is_null() || (*cf).io.read == 0 {
30 (*f).flags |= F_ERR;
31 (*f)._err = 1;
32 return 0;
33 }
34 let func: CookieReadFn = core::mem::transmute((*cf).io.read);
35 let n = func((*cf).cookie, buf as *mut c_char, len);
36 if n <= 0 {
37 if n == 0 {
38 (*f).flags |= F_EOF;
39 } else {
40 (*f).flags |= F_ERR;
41 (*f)._err = 1;
42 }
43 return 0;
44 }
45 n as usize
46}
47
48unsafe extern "C" fn cookie_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
49 let cf = (*f).cookie as *mut CookieFile;
50 if cf.is_null() || (*cf).io.write == 0 { return len; }
51 let func: CookieWriteFn = core::mem::transmute((*cf).io.write);
52 let buffered = if (*f).wbase.is_null() { 0 } else { (*f).wpos as usize - (*f).wbase as usize };
53 if buffered > 0 {
54 let n = func((*cf).cookie, (*f).wbase as *const c_char, buffered);
55 if n != buffered as isize {
56 (*f).wpos = core::ptr::null_mut();
57 (*f).wbase = core::ptr::null_mut();
58 (*f).wend = core::ptr::null_mut();
59 (*f).flags |= F_ERR;
60 (*f).flags |= F_ERR;
61 return 0;
62 }
63 (*f).wbase = (*f).buf;
64 (*f).wpos = (*f).buf;
65 (*f).wend = (*f).buf.add((*f).buf_size);
66 }
67 if len > 0 {
68 let n = func((*cf).cookie, buf as *const c_char, len);
69 if n < 0 { (*f).flags |= F_ERR; return 0; }
70 return n as usize;
71 }
72 0
73}
74
75unsafe extern "C" fn cookie_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
76 let cf = (*f).cookie as *mut CookieFile;
77 if cf.is_null() || (*cf).io.seek == 0 {
78 ERRNO = 95; return -1;
80 }
81 if whence < 0 || whence > 2 {
82 ERRNO = EINVAL;
83 return -1;
84 }
85 let func: CookieSeekFn = core::mem::transmute((*cf).io.seek);
86 let mut o = off;
87 let r = func((*cf).cookie, &mut o as *mut i64, whence);
88 if r < 0 { return -1; }
89 o
90}
91
92unsafe extern "C" fn cookie_close(f: *mut FILE) -> c_int {
93 let cf = (*f).cookie as *mut CookieFile;
94 if cf.is_null() { return 0; }
95 let mut r = 0;
96 if (*cf).io.close != 0 {
97 let func: CookieCloseFn = core::mem::transmute((*cf).io.close);
98 r = func((*cf).cookie);
99 }
100 crate::free(cf as *mut c_void);
101 (*f).cookie = core::ptr::null_mut();
102 r
103}
104
105#[no_mangle]
106pub unsafe extern "C" fn fopencookie(cookie: *mut c_void, mode: *const c_char, io_funcs: CookieIo) -> *mut FILE {
107 if mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
108 let m = *mode;
109 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
110 ERRNO = EINVAL;
111 return core::ptr::null_mut();
112 }
113 let f = crate::calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
114 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
115 let cf = crate::calloc(1, core::mem::size_of::<CookieFile>()) as *mut CookieFile;
116 if cf.is_null() { crate::free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
117 (*cf).cookie = cookie;
118 (*cf).io = io_funcs;
119
120 (*f).fd = -1;
121 (*f).cookie = cf as *mut c_void;
122 (*f).buf = buf_ptr(f);
123 (*f).buf_size = BUFSIZ;
124 (*f).lbf = -1;
125 (*f).read_fn = Some(cookie_read);
126 (*f).write_fn = Some(cookie_write);
127 (*f).seek_fn = Some(cookie_seek);
128 (*f).close = Some(cookie_close);
129 if !crate::strchr(mode as *const u8, b'+' as c_int).is_null() {
130 (*f).flags = 0;
131 } else if m == b'r' as c_char {
132 (*f).flags = F_NOWR;
133 } else {
134 (*f).flags = F_NORD;
135 }
136 if m == b'a' as c_char { (*f).flags |= F_APP; }
137 f
138}
139
140#[repr(C)]
145struct WmsCookie {
146 bufp: *mut *mut wchar_t,
147 sizep: *mut usize,
148 pos: usize,
149 buf: *mut wchar_t,
150 len: usize,
151 space: usize,
152 need: u8,
154 have: u8,
155 cp: u32,
156}
157
158unsafe fn wms_emit(c: *mut WmsCookie, wc: u32) {
159 if (*c).pos >= (*c).space {
160 let len2 = ((*c).space * 2 + 1) | ((*c).pos + 1);
161 if len2 > (isize::MAX as usize) / 4 { return; }
162 let newbuf = crate::realloc((*c).buf as *mut c_void, len2 * 4) as *mut wchar_t;
163 if newbuf.is_null() { ERRNO = ENOMEM; return; }
164 core::ptr::write_bytes((newbuf as *mut u8).add((*c).space * 4), 0, (len2 - (*c).space) * 4);
165 (*c).buf = newbuf;
166 (*c).space = len2;
167 if !(*c).bufp.is_null() { *(*c).bufp = newbuf; }
168 }
169 *(*c).buf.add((*c).pos) = wc as wchar_t;
170 (*c).pos += 1;
171 if (*c).pos > (*c).len { (*c).len = (*c).pos; }
172 *(*c).buf.add((*c).pos) = 0;
173 if !(*c).sizep.is_null() { *(*c).sizep = (*c).pos; }
174}
175
176unsafe extern "C" fn wms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
177 let c = (*f).cookie as *mut WmsCookie;
178 if c.is_null() { return 0; }
179 for i in 0..len {
180 let b = *buf.add(i);
181 if (*c).need == 0 {
182 if b < 0x80 {
183 wms_emit(c, b as u32);
184 } else if b >= 0xc2 && b <= 0xdf {
185 (*c).need = 1;
186 (*c).have = 0;
187 (*c).cp = (b & 0x1f) as u32;
188 } else if b >= 0xe0 && b <= 0xef {
189 (*c).need = 2;
190 (*c).have = 0;
191 (*c).cp = (b & 0x0f) as u32;
192 } else if b >= 0xf0 && b <= 0xf4 {
193 (*c).need = 3;
194 (*c).have = 0;
195 (*c).cp = (b & 0x07) as u32;
196 } else {
197 wms_emit(c, 0xfffd);
198 }
199 } else if b & 0xc0 == 0x80 {
200 (*c).cp = ((*c).cp << 6) | (b & 0x3f) as u32;
201 (*c).have += 1;
202 if (*c).have == (*c).need {
203 wms_emit(c, (*c).cp);
204 (*c).need = 0;
205 (*c).have = 0;
206 (*c).cp = 0;
207 }
208 } else {
209 wms_emit(c, 0xfffd);
212 (*c).need = 0;
213 (*c).have = 0;
214 (*c).cp = 0;
215 if b < 0x80 {
216 wms_emit(c, b as u32);
217 } else if b >= 0xc2 && b <= 0xdf {
218 (*c).need = 1;
219 (*c).cp = (b & 0x1f) as u32;
220 } else if b >= 0xe0 && b <= 0xef {
221 (*c).need = 2;
222 (*c).cp = (b & 0x0f) as u32;
223 } else if b >= 0xf0 && b <= 0xf4 {
224 (*c).need = 3;
225 (*c).cp = (b & 0x07) as u32;
226 } else {
227 wms_emit(c, 0xfffd);
228 }
229 }
230 }
231 len
232}
233
234unsafe extern "C" fn wms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
235 let c = (*f).cookie as *mut WmsCookie;
236 if c.is_null() || whence < 0 || whence > 2 {
237 ERRNO = EINVAL;
238 return -1;
239 }
240 let base: i64 = match whence {
241 0 => 0,
242 1 => (*c).pos as i64,
243 _ => (*c).len as i64,
244 };
245 if off < -base || off > (isize::MAX as i64) / 4 - base {
246 ERRNO = EINVAL;
247 return -1;
248 }
249 (*c).pos = (base + off) as usize;
250 (*c).need = 0;
251 (*c).have = 0;
252 (*c).cp = 0;
253 (*c).pos as i64
254}
255
256unsafe extern "C" fn wms_close(_f: *mut FILE) -> c_int {
257 0
258}
259
260#[no_mangle]
261pub unsafe extern "C" fn open_wmemstream(bufp: *mut *mut wchar_t, sizep: *mut usize) -> *mut FILE {
262 if bufp.is_null() || sizep.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
263 let f = crate::calloc(1, core::mem::size_of::<FILE>() + 1) as *mut FILE;
264 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
265 let c = crate::calloc(1, core::mem::size_of::<WmsCookie>()) as *mut WmsCookie;
266 if c.is_null() { crate::free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
267 let buf = crate::calloc(1, 4) as *mut wchar_t;
268 if buf.is_null() {
269 crate::free(c as *mut c_void);
270 crate::free(f as *mut c_void);
271 ERRNO = ENOMEM;
272 return core::ptr::null_mut();
273 }
274 (*c).bufp = bufp;
275 (*c).sizep = sizep;
276 (*c).buf = buf;
277 (*c).space = 1;
278 *bufp = buf;
279 *sizep = 0;
280 (*f).fd = -1;
281 (*f).cookie = c as *mut c_void;
282 let base = (f as *mut u8).add(core::mem::size_of::<FILE>());
283 (*f).buf = base;
284 (*f).buf_size = 0;
285 (*f).lbf = -1;
286 (*f).flags = F_NORD;
287 (*f).write_fn = Some(wms_write);
288 (*f).seek_fn = Some(wms_seek);
289 (*f).close = Some(wms_close);
290 (*f).mode = 1;
291 f
292}
293
294unsafe fn strfmon_impl(mut s: *mut c_char, n: usize, fmt: *const c_char, mut ap: VaList) -> isize {
299 let start = s;
300 let mut cap = n;
301 let mut f = fmt;
302 while cap > 0 && *f != 0 {
303 if *f as u8 != b'%' {
304 *s = *f;
305 s = s.add(1);
306 f = f.add(1);
307 cap -= 1;
308 continue;
309 }
310 f = f.add(1);
311 if *f as u8 == b'%' {
312 *s = *f;
313 s = s.add(1);
314 f = f.add(1);
315 cap -= 1;
316 continue;
317 }
318 let mut fill = b' ' as c_char;
319 let mut nogrp = true; let mut negpar = false;
321 let mut nosym = false;
322 let mut left = false;
323 let mut plus = false;
324 loop {
325 match *f as u8 {
326 b'=' => { f = f.add(1); fill = *f; f = f.add(1); }
327 b'^' => { nogrp = true; f = f.add(1); }
328 b'(' => { negpar = true; f = f.add(1); }
329 b'+' => { plus = true; f = f.add(1); }
330 b'!' => { nosym = true; f = f.add(1); }
331 b'-' => { left = true; f = f.add(1); }
332 _ => break,
333 }
334 }
335 let mut fw = 0usize;
336 while *f as u8 >= b'0' && *f as u8 <= b'9' {
337 fw = fw * 10 + (*f as u8 - b'0') as usize;
338 f = f.add(1);
339 }
340 let mut lp = 1usize;
341 if *f as u8 == b'#' {
342 f = f.add(1);
343 lp = 0;
344 while *f as u8 >= b'0' && *f as u8 <= b'9' {
345 lp = lp * 10 + (*f as u8 - b'0') as usize;
346 f = f.add(1);
347 }
348 if lp == 0 { lp = 1; }
349 }
350 let mut rp = 2usize;
351 if *f as u8 == b'.' {
352 rp = 0;
353 f = f.add(1);
354 while *f as u8 >= b'0' && *f as u8 <= b'9' {
355 rp = rp * 10 + (*f as u8 - b'0') as usize;
356 f = f.add(1);
357 }
358 }
359 let _intl = *f as u8 == b'i';
360 if *f != 0 { f = f.add(1); }
361 let x = ap.next_arg::<f64>();
362 let neg = x < 0.0;
363 let ax = if neg { -x } else { x };
364
365 let mut num = [0 as c_char; 256];
367 let rn = crate::snprintf(
368 num.as_mut_ptr(),
369 num.len(),
370 b"%.*f\0".as_ptr() as *const c_char,
371 rp as c_int,
372 ax,
373 );
374 let mut nlen = core::cmp::min(rn.max(0) as usize, num.len() - 1);
375
376 let mut dot = nlen;
378 for i in 0..nlen {
379 if num[i] as u8 == b'.' { dot = i; break; }
380 }
381 let mut int_digits = dot;
382 let zero_pad = if int_digits < lp { lp - int_digits } else { 0 };
384
385 let mut grouped = [0 as c_char; 320];
387 let mut glen = 0usize;
388 if !nogrp && int_digits > 3 {
389 let first = int_digits % 3;
390 let mut i = 0usize;
391 while i < int_digits {
392 if i > 0 && (i - first) % 3 == 0 { grouped[glen] = b',' as c_char; glen += 1; }
393 grouped[glen] = num[i]; glen += 1; i += 1;
394 }
395 } else {
396 for i in 0..int_digits { grouped[glen] = num[i]; glen += 1; }
397 }
398 let _ = &mut int_digits;
399 let _ = &mut nlen;
400
401 let mut core = [0 as c_char; 640];
403 let mut clen = 0usize;
404 let parens = negpar && neg;
405 if parens { core[clen] = b'(' as c_char; clen += 1; }
406 else if neg { core[clen] = b'-' as c_char; clen += 1; }
407 else if plus { core[clen] = b'+' as c_char; clen += 1; }
408 for _ in 0..zero_pad {
409 core[clen] = b'0' as c_char; clen += 1;
410 }
411 for i in 0..glen { core[clen] = grouped[i]; clen += 1; }
412 for i in dot..nlen { core[clen] = num[i]; clen += 1; }
413 if parens { core[clen] = b')' as c_char; clen += 1; }
414
415 let width = if fw > clen { fw } else { clen };
416 let pad = width - clen;
417 if left {
418 for i in 0..clen {
419 if cap <= 1 { break; }
420 *s = core[i]; s = s.add(1); cap -= 1;
421 }
422 for _ in 0..pad {
423 if cap <= 1 { break; }
424 *s = b' ' as c_char; s = s.add(1); cap -= 1;
425 }
426 } else {
427 for _ in 0..pad {
428 if cap <= 1 { break; }
429 *s = fill; s = s.add(1); cap -= 1;
430 }
431 for i in 0..clen {
432 if cap <= 1 { break; }
433 *s = core[i]; s = s.add(1); cap -= 1;
434 }
435 }
436 let _ = nosym;
437 }
438 *s = 0;
439 (s as usize - start as usize) as isize
440}
441
442#[no_mangle]
443pub unsafe extern "C" fn strfmon(s: *mut c_char, n: usize, fmt: *const c_char, args: ...) -> isize {
444 strfmon_impl(s, n, fmt, args)
445}
446
447#[no_mangle]
448pub unsafe extern "C" fn strfmon_l(
449 s: *mut c_char,
450 n: usize,
451 _loc: locale_t,
452 fmt: *const c_char,
453 args: ...,
454) -> isize {
455 strfmon_impl(s, n, fmt, args)
456}
457
458#[no_mangle]
463pub static mut getdate_err: c_int = 0;
464
465static mut GETDATE_TM: crate::tm = crate::tm {
466 tm_sec: 0,
467 tm_min: 0,
468 tm_hour: 0,
469 tm_mday: 0,
470 tm_mon: 0,
471 tm_year: 0,
472 tm_wday: 0,
473 tm_yday: 0,
474 tm_isdst: 0,
475 tm_gmtoff: 0,
476 tm_zone: core::ptr::null(),
477};
478
479#[no_mangle]
480pub unsafe extern "C" fn getdate(s: *const c_char) -> *mut crate::tm {
481 if s.is_null() {
482 getdate_err = 1;
483 return core::ptr::null_mut();
484 }
485 let datemsk = crate::getenv(b"DATEMSK\0".as_ptr() as *const c_char);
486 if datemsk.is_null() {
487 getdate_err = 1;
488 return core::ptr::null_mut();
489 }
490 let f = crate::fopen(datemsk, b"r\0".as_ptr() as *const c_char);
491 if f.is_null() {
492 getdate_err = if ERRNO == ENOMEM { 6 } else { 2 };
493 return core::ptr::null_mut();
494 }
495 let mut fmt = [0 as c_char; 128];
496 let mut found = false;
497 while !crate::fgets(fmt.as_mut_ptr(), fmt.len() as c_int, f).is_null() {
498 let mut end: *mut c_char = core::ptr::null_mut();
499 let p = crate::strptime(s, fmt.as_ptr(), &raw mut GETDATE_TM);
500 if !p.is_null() && *p == 0 {
501 found = true;
502 break;
503 }
504 let _ = &mut end;
505 }
506 if !found && crate::ferror(f) != 0 { getdate_err = 5; }
507 crate::fclose(f);
508 if found {
509 getdate_err = 0;
510 return &raw mut GETDATE_TM;
511 }
512 if getdate_err == 0 { getdate_err = 7; }
513 core::ptr::null_mut()
514}