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