21 #ifndef P99_CONSTRAINT_H
22 #define P99_CONSTRAINT_H
51 void exit_handler_s(
const char * restrict p00_msg,
52 void * restrict p00_ptr,
62 void ignore_handler_s(
const char * restrict p00_msg,
63 void * restrict p00_ptr,
79 void abort_handler_s(
const char * restrict p00_msg,
80 void * restrict p00_ptr,
86 void * restrict p00_ptr,
100 #define P00_JMP_BUF_FILE P99_THREAD_LOCAL(p00_jmp_buf_file)
101 #define P00_JMP_BUF_CONTEXT P99_THREAD_LOCAL(p00_jmp_buf_context)
102 #define P00_JMP_BUF_INFO P99_THREAD_LOCAL(p00_jmp_buf_info)
106 #if __STDC_WANT_LIB_EXT1__ && !defined(__STDC_LIB_EXT1__)
109 return strlen(
strerror(p00_errnum));
113 #if (_XOPEN_SOURCE >= 600)
115 int p00_strerror(
int p00_errname,
size_t p00_maxsize,
char p00_s[p00_maxsize]) {
123 # if _GNU_SOURCE && __GLIBC__
124 char * p00_ret = strerror_r(p00_errname, p00_s, p00_maxsize);
125 if ((uintptr_t)p00_ret < 2048)
return (intptr_t)p00_ret;
126 if (p00_ret != p00_s) {
127 if (strlen(p00_ret) < p00_maxsize) {
128 strcpy(p00_s, p00_ret);
136 return strerror_r(p00_errname, p00_s, p00_maxsize);
139 #elif __STDC_WANT_LIB_EXT1__ && defined(__STDC_LIB_EXT1__)
141 int p00_strerror(
int p00_errname,
size_t p00_maxsize,
char p00_s[p00_maxsize]) {
142 return strerror_s(p00_s, p00_maxsize, p00_errname);
146 int p00_strerror(
int p00_errname,
size_t p00_maxsize,
char p00_s[p00_maxsize]) {
149 if (p00_len > p00_maxsize - 1) {
150 p00_len = p00_maxsize - 1;
153 strncpy(p00_s,
strerror(p00_errname), p00_len);
160 char const* p00_strerror_r(
int p00_errname,
size_t p00_maxsize,
char p00_s[p00_maxsize]) {
161 p00_strerror(p00_errname, p00_maxsize, p00_s);
165 #define P00_STRERROR2(E, STR) p00_strerror(E, sizeof(STR), STR)
167 #define P99_STRERROR_MAX 256
169 #define p00_strerror(...) \
170 P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
171 (p00_strerror(__VA_ARGS__, P99_STRERROR_MAX, (char[P99_STRERROR_MAX]))) \
172 (P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
173 (P00_STRERROR2(__VA_ARGS__)) \
174 (p00_strerror(__VA_ARGS__)))
176 #if __STDC_WANT_LIB_EXT1__ && !defined(__STDC_LIB_EXT1__)
178 void p99_constraint_handler(
const char * restrict p00_msg,
179 void * restrict p00_ptr,
185 size_t strnlen_s(
const char *p00_s,
size_t p00_maxsize) {
186 size_t p00_ret = p00_maxsize;
187 if (p00_s && p00_maxsize) {
188 char const* p00_pos = memchr(p00_s, 0, p00_maxsize);
189 if (p00_pos) p00_ret = p00_pos - p00_s;
196 if (!p00_maxsize || p00_maxsize >
RSIZE_MAX)
197 p99_constraint_handler(
198 ", call to strerror_s, dynamic constraint violation",
204 int p00_ret = p00_strerror(p00_errnum, p00_maxsize, p00_s);
210 if (p00_maxsize > 3) memset(p00_s + (p00_maxsize - 4),
'.', 3);
215 p00_ret = snprintf(p00_s, p00_maxsize,
"unknown <%d> error", p00_errnum);
216 if (!p00_ret || (p00_ret < p00_maxsize)) {
218 if (p00_maxsize > 3) memset(p00_s + (p00_maxsize - 4),
'.', 3);
223 fprintf(stderr,
"strerror_r returned %d\n", p00_ret);
233 char const* p00_strerror_s(
char *p00_s,
rsize_t p00_maxsize,
errno_t p00_errnum) {
238 # define P00_STRERROR(E, S, STR) p00_strerror_s(STR, S, E)
240 # define P00_STRERROR(...) p00_strerror_r(__VA_ARGS__)
243 #define P00_STRERROR02(E, STR) P00_STRERROR(E, sizeof(STR), STR)
245 #define P99_STRERROR(...) \
246 P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
247 (P00_STRERROR(__VA_ARGS__, P99_STRERROR_MAX, (char[P99_STRERROR_MAX]){ 0 })) \
248 (P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
249 (P00_STRERROR02(__VA_ARGS__)) \
250 (P00_STRERROR(__VA_ARGS__)))
253 void p00_constraint_report(
errno_t p00_cond,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
254 char p00_str[p00_ilen10] =
P99_INIT;
255 if (!p00_context) p00_context = P00_JMP_BUF_CONTEXT;
256 if (!p00_context) p00_context =
"<unknown function>";
257 if (!p00_info) p00_info = P00_JMP_BUF_INFO;
258 if (!p00_file) p00_file = P00_JMP_BUF_FILE;
259 if (!p00_file) p00_file =
"<unknown location>";
260 fputs(p00_context, stderr);
262 fputs(p00_file, stderr);
265 fputs(p00_info, stderr);
268 fputs(
"exception ", stderr);
272 fputs(p00_errname, stderr);
277 sprintf(p00_str,
"%d", p00_cond);
278 fputs(p00_str, stderr);
283 fputs(
", library error: ", stderr);
284 fputs(p00_str, stderr);
291 void * restrict p00_ptr,
294 p00_constraint_report(p00_err, 0, 0, p00_msg);
299 void * restrict p00_ptr,
309 void * restrict p00_ptr,
312 p00_constraint_report(p00_err, 0, 0, p00_msg);
313 fputs(
"runtime constraint violation: ", stderr);
320 void * restrict p00_ptr,
324 p00_constraint_report(p00_err, 0, 0, p00_msg);
325 fputs(
"runtime constraint violation: ", stderr);
329 #ifndef P99_CONSTRAINT_HANDLER
330 # define P99_CONSTRAINT_HANDLER exit_handler_s
333 #if __STDC_WANT_LIB_EXT1__
338 void report_handler_s(
const char * restrict p00_msg,
339 void * restrict p00_ptr,
343 void exit_handler_s(
const char * restrict p00_msg,
344 void * restrict p00_ptr,
351 void report_handler_s(
const char * restrict p00_msg,
352 void * restrict p00_ptr,
359 void exit_handler_s(
const char * restrict p00_msg,
360 void * restrict p00_ptr,
366 void p99_constraint_handler(
const char * restrict p00_msg,
367 void * restrict p00_ptr,
369 constraint_handler_t p00_func = atomic_load_explicit(&p00_constraint_handler, memory_order_acquire);
370 if (p00_func) p00_func(p00_msg, p00_ptr, p00_err);
374 # ifndef __STDC_LIB_EXT1__
377 void ignore_handler_s(
const char * restrict p00_msg,
378 void * restrict p00_ptr,
385 void abort_handler_s(
const char * restrict p00_msg,
386 void * restrict p00_ptr,
394 return atomic_exchange_explicit(&p00_constraint_handler, p00_hand, memory_order_acq_rel);
400 errno_t p00_constraint_call(
errno_t p00_cond,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
402 if (p00_file) P00_JMP_BUF_FILE = p00_file;
403 if (p00_context) P00_JMP_BUF_CONTEXT = p00_context;
406 atomic_thread_fence(memory_order_seq_cst); \
407 p99_constraint_handler(p00_info, 0, p00_cond);
412 #define P00_CONSTRAINT_INFO(F) ", call to " #F ", dynamic constraint violation"
415 #define P99_CONSTRAINT_TRIGGER(E, I) \
416 p00_constraint_call((E), P99_STRINGIFY(__LINE__), __func__, I)
418 #define P00_CONSTRAINT_CALL3(F, I, C) \
419 P99_CONSTRAINT_TRIGGER(F C, I)
421 #define P00_CONSTRAINT_CALL1(F) P00_CONSTRAINT_CALL3(F, P00_CONSTRAINT_INFO(F), ())
423 #define P00_CONSTRAINT_CALL0(F, ...) P00_CONSTRAINT_CALL3(F, P00_CONSTRAINT_INFO(F), (__VA_ARGS__))
425 #define P99_CONSTRAINT_CALL(...) \
426 P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
427 (P00_CONSTRAINT_CALL1(__VA_ARGS__)) \
428 (P00_CONSTRAINT_CALL0(__VA_ARGS__))
431 # if !defined(__STDC_LIB_EXT1__) || defined(P00_DOXYGEN)
434 errno_t p00_memcpy_s(_Bool p00_overlap,
435 void * restrict p00_s1,
rsize_t p00_s1max,
436 const void * restrict p00_s2,
rsize_t p00_n) {
438 if (!p00_s1) { p00_ret =
EINVAL;
goto P00_SEVERE; }
439 if (p00_s1max >
RSIZE_MAX) { p00_ret = EDOM;
goto P00_SEVERE; }
440 if (!p00_s2) { p00_ret =
EINVAL;
goto P00_ERR; }
441 if (p00_n >
RSIZE_MAX || p00_n > p00_s1max) { p00_ret = EDOM;
goto P00_ERR; }
443 unsigned char const* p00_c1 = p00_s1;
444 unsigned char const* p00_c2 = p00_s2;
447 if ((p00_c1 <= p00_c2 && p00_c2 < (p00_c1 + p00_s1max))
448 || (p00_c2 <= p00_c1 && p00_c1 < (p00_c2 + p00_n))) {
449 p00_ret =
EINVAL;
goto P00_ERR;
451 memcpy(p00_s1, p00_s2, p00_n);
453 memmove(p00_s1, p00_s2, p00_n);
457 if (p00_s1max) memset(p00_s1, 0, p00_s1max);
463 # define memcpy_s(S1, S1MAX, S2, N) P99_CONSTRAINT_TRIGGER(p00_memcpy_s(false, (S1), (S1MAX), (S2), (N)), "memcpy_s runtime constraint violation")
465 # define memmove_s(S1, S1MAX, S2, N) P99_CONSTRAINT_TRIGGER(p00_memcpy_s(true, (S1), (S1MAX), (S2), (N)), "memmove_s runtime constraint violation")
469 const void * restrict p00_s2) {
470 size_t p00_len =
strnlen_s(p00_s2, p00_s1max) + 1;
471 return p00_memcpy_s(
false, p00_s1, p00_s1max, p00_s2, p00_len);
475 # define strcpy_s(S1, S1MAX, S2) P99_CONSTRAINT_TRIGGER(p00_strcpy_s((S1), (S1MAX), (S2)), "strcpy_s runtime constraint violation")
478 errno_t p00_strncpy_s(
char * restrict p00_s1,
480 const char * restrict p00_s2,
482 if (!p00_s1 || !p00_s1max || p00_s1max >
RSIZE_MAX)
return memcpy_s(p00_s1, p00_s1max, p00_s2, p00_n);
483 if (!p00_s2 || p00_n >
RSIZE_MAX)
return memcpy_s(p00_s1, p00_s1max, p00_s2, p00_n);
485 size_t p00_len =
strnlen_s(p00_s2, p00_n - 1) + 1;
488 if (p00_s1max < p00_len)
return memcpy_s(p00_s1, p00_s1max, 0, 0);
490 size_t p00_ret =
memcpy_s(p00_s1, p00_s1max, p00_s2, p00_len - 1);
491 p00_s1[p00_len - 1] = 0;
495 # define strncpy_s(S1, S1MAX, S2, N) P99_CONSTRAINT_TRIGGER(p00_strncpy_s((S1), (S1MAX), (S2), (N)), "strncpy_s runtime constraint violation")
498 errno_t p00_strcat_s(
char * restrict p00_s1,
500 const char * restrict p00_s2) {
501 if (!p00_s1 || !p00_s1max || p00_s1max >
RSIZE_MAX)
return memcpy_s(p00_s1, p00_s1max, p00_s2, 0);
502 if (!p00_s2)
return memcpy_s(p00_s1, p00_s1max, p00_s2, 0);
503 size_t p00_l1 =
strnlen_s(p00_s1, p00_s1max);
505 if (p00_l1 >= p00_s1max)
return memcpy_s(p00_s1, 1, 0, 0);
506 else p00_s1max -= p00_l1;
509 size_t p00_l2 =
strnlen_s(p00_s2, p00_s1max) + 1;
510 if (p00_l2 > p00_s1max)
return memcpy_s(p00_s1, 1, p00_s2, 0);
511 size_t p00_ret =
strncpy_s(p00_s1 + p00_l1, p00_s1max, p00_s2, p00_l2);
512 if (p00_ret) p00_s1[0] = 0;
517 # define strcat_s(S1, S1MAX, S2) P99_CONSTRAINT_TRIGGER(p00_strcat_s((S1), (S1MAX), (S2)), "strcat_s runtime constraint violation")
520 errno_t p00_strncat_s(
char * restrict p00_s1,
522 const char * restrict p00_s2,
524 if (!p00_s1 || !p00_s1max || p00_s1max >
RSIZE_MAX)
return memcpy_s(p00_s1, p00_s1max, p00_s2, 0);
526 size_t p00_l1 =
strnlen_s(p00_s1, p00_s1max);
528 if (p00_l1 >= p00_s1max)
return memcpy_s(p00_s1, 1, 0, 0);
529 else p00_s1max -= p00_l1;
532 size_t p00_l2 =
strnlen_s(p00_s2, p00_n) + 1;
533 if (p00_l2 > p00_s1max)
return memcpy_s(p00_s1, 1, p00_s2, 0);
534 size_t p00_ret =
strncpy_s(p00_s1 + p00_l1, p00_s1max, p00_s2, p00_l2);
535 if (p00_ret) p00_s1[0] = 0;
540 # define strncat_s(S1, S1MAX, S2, N) P99_CONSTRAINT_TRIGGER(p00_strncat_s((S1), (S1MAX), (S2), (N)), "strncat_s runtime constraint violation")
543 void *p00_bsearch_s(
char const* p00_file,
char const* p00_context,
544 const void *p00_key,
const void *p00_base,
546 int (*p00_compar)(
const void *,
const void *,
void *),
550 p00_constraint_call(EDOM, p00_file, p00_context,
"bsearch_s runtime constraint violation");
551 }
else if (p00_nmemb && (!p00_key || !p00_base || !p00_compar)) {
552 p00_constraint_call(
EINVAL, p00_file, p00_context,
"bsearch_s runtime constraint violation");
554 register unsigned char const (*p00_dbase)[p00_size] = (
void*)p00_base;
559 for (
register size_t p00_bot = -1, p00_top = p00_nmemb;
560 (p00_top - p00_bot) != 1;) {
562 register size_t p00_med = (p00_bot + p00_top) / 2;
568 int co = p00_compar(p00_key, p00_dbase + p00_med, p00_ctx);
569 if (!co)
return (
void*)(p00_dbase + p00_med);
570 else if (co < 0) p00_top = p00_med;
571 else p00_bot = p00_med;
579 #define bsearch_s(...) p00_bsearch_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
582 errno_t p00_getenv_s(
char const* p00_file,
char const* p00_context,
583 size_t * restrict p00_len,
584 char * restrict p00_value,
rsize_t p00_maxsize,
585 const char * restrict p00_name) {
590 p00_constraint_call(p00_ret, p00_file, p00_context,
"getenv_s runtime constraint violation");
591 }
else if (!p00_name || (p00_maxsize && !p00_value)) {
593 p00_constraint_call(p00_ret, p00_file, p00_context,
"getenv_s runtime constraint violation");
595 char const*
const p00_found = getenv(p00_name);
597 p00_le = strlen(p00_found);
598 if (p00_le < p00_maxsize) strcpy(p00_value, p00_found);
600 if (p00_maxsize) p00_value[0] =
'\0';
603 if (p00_len) *p00_len = p00_le;
608 #define getenv_s(...) p00_getenv_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
611 errno_t p00_tmpfile_s(
char const* p00_file,
char const* p00_context,
612 FILE * restrict * restrict p00_streamptr) {
614 if (!p00_streamptr) {
617 *p00_streamptr = tmpfile();
618 if (!*p00_streamptr) {
623 if (p00_ret) p00_constraint_call(p00_ret, p00_file, p00_context,
"tmpfile_s runtime constraint violation");
628 #define tmpfile_s(...) p00_tmpfile_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
631 errno_t p00_tmpnam_s(
char const* p00_file,
char const* p00_context,
632 char *p00_s,
rsize_t p00_maxsize) {
640 char * p00_r = tmpnam(p00_b);
641 char p00_p = p00_b[L_tmpnam - 1];
642 p00_b[L_tmpnam - 1] = 0;
643 size_t p00_l = strlen(p00_b);
644 if (!p00_r || ((p00_l == (L_tmpnam - 1)) && p00_p) || (p00_l >= p00_maxsize)) {
649 strcpy(p00_s, p00_r);
652 if (p00_ret) p00_constraint_call(p00_ret, p00_file, p00_context,
"tmpnam_s runtime constraint violation");
657 #define tmpnam_s(...) p00_tmpnam_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
660 char *p00_gets_s(
char const* p00_file,
char const* p00_context,
673 p00_ret = fgets(p00_s, p00_n - 1, stdin);
675 size_t p00_l = strlen(p00_s);
676 if (p00_s[p00_l - 1] ==
'\n') {
678 p00_s[p00_l - 1] =
'\0';
684 char* p00_r = fgets(p00_b, 2, stdin);
693 p00_constraint_call(p00_err, p00_file, p00_context,
"gets_s runtime constraint violation");
701 #define gets_s(...) p00_gets_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
705 bool p00_isin0(
char p00_c,
706 rsize_t p00_s2l, uint8_t
const p00_s2[
const restrict p00_s2l]) {
708 for (
rsize_t p00_i = 0; p00_i < (p00_s2l - 1); ++p00_i)
717 rsize_t p99_span(
rsize_t p00_s1l, uint8_t p00_s1[
const restrict p00_s1l],
718 rsize_t p00_s2l, uint8_t
const p00_s2[
const restrict p00_s2l]) {
719 for (
rsize_t p00_ret = 0; p00_ret < p00_s1l; ++p00_ret) {
720 if (!p00_s1[p00_ret] || !P00_ISIN(p00_s1[p00_ret], p00_s2l, p00_s2))
727 rsize_t p00_cskip(
rsize_t p00_s1l, uint8_t p00_s1[
const restrict p00_s1l],
728 rsize_t p00_s2l, uint8_t
const p00_s2[
const restrict p00_s2l]) {
730 for (; p00_ret < p00_s1l && p00_s1[p00_ret]; ++p00_ret) {
731 if (P00_ISIN(p00_s1[p00_ret], p00_s2l, p00_s2)) {
732 p00_s1[p00_ret] =
'\0';
740 uint8_t *p00_strtok_inner(
742 uint8_t p00_ret0[restrict (*p00_s1max)],
744 const uint8_t p00_s2[
const restrict p00_s2max],
745 uint8_t ** restrict p00_ptr) {
749 register uint8_t * p00_ret = p00_ret0;
751 register size_t const p00_l = p99_span(*p00_s1max, p00_ret, p00_s2max, p00_s2);
752 if (p00_l < *p00_s1max) {
756 register size_t const p00_k = p00_cskip(*p00_s1max, p00_ret, p00_s2max, p00_s2);
758 if (p00_k && ((p00_k > 1) || (*p00_s1max == 1) || !p00_ret[1])) {
759 *p00_ptr = p00_ret + p00_k;
768 char *p00_strtok_s(
char const* p00_file,
char const* p00_context,
770 uint8_t p00_s1[restrict (*p00_s1max)],
772 const uint8_t p00_s2[
const restrict p00_s2max],
773 uint8_t ** restrict p00_ptr) {
775 uint8_t *p00_ret = 0;
784 p00_constraint_call(p00_err, p00_file, p00_context,
"strtok_s runtime constraint violation");
789 p00_ret = p00_strtok_inner(p00_s1max, p00_s1, p00_s2max, p00_s2, p00_ptr);
791 p00_ret = p00_strtok_inner(p00_s1max, *p00_ptr, p00_s2max, p00_s2, p00_ptr);
794 return (
char*)p00_ret;
797 #define P00_STRSIZE(S) \
800 (char *, strlen(S)+1), \
801 (char const*, strlen(S)+1), \
802 (char volatile*, strlen(S)+1), \
803 (char volatile const*, strlen(S)+1), \
804 (char *restrict, strlen(S)+1), \
805 (char const*restrict, strlen(S)+1), \
806 (char volatile*restrict, strlen(S)+1), \
807 (char volatile const*restrict, strlen(S)+1) \
812 #define strtok_s(S1, S1MAX, S2, PTR) \
813 p00_strtok_s(P99_STRINGIFY(__LINE__), __func__, \
814 S1MAX, (uint8_t*restrict)(S1), \
815 P00_STRSIZE(S2), (uint8_t const*restrict)(S2), \
818 #define P00_SPAN_DECLARE(NAME, SET) \
821 rsize_t P99_PASTE2(p99_span_, NAME)(rsize_t p00_s1l, uint8_t p00_s1[const restrict p00_s1l]) { \
822 return p99_span(p00_s1l, p00_s1, sizeof(SET)-1, (uint8_t const*)(char const[]){ SET }); \
825 char* P99_PASTE2(p99_strtok_, NAME)(rsize_t * restrict p00_s1max, \
826 char p00_s1[restrict (*p00_s1max)], \
827 char ** restrict p00_ptr) { \
828 return strtok_s(p00_s1, p00_s1max, SET, p00_ptr); \
830 P99_MACRO_END(P00_SPAN_DECLARE, NAME)
834 P00_SPAN_DECLARE(blank, P00_BLANK);
835 P00_SPAN_DECLARE(space, P00_SPACE);
836 P00_SPAN_DECLARE(lower, P00_LOWER);
837 P00_SPAN_DECLARE(upper, P00_UPPER);
838 P00_SPAN_DECLARE(digit, P00_DIGIT);
839 P00_SPAN_DECLARE(xdigit, P00_XDIGIT);
840 P00_SPAN_DECLARE(alpha, P00_ALPHA);
841 P00_SPAN_DECLARE(alnum, P00_ALNUM);
846 bool p00_tm_valid(
struct tm
const* p00_tm) {
852 ((61u > (
unsigned)p00_tm->tm_sec)
854 + (60u > (
unsigned)p00_tm->tm_min)
855 + (24u > (
unsigned)p00_tm->tm_hour)
856 + (32u > ((
unsigned)p00_tm->tm_mday - 1u))
857 + (12u > (
unsigned)p00_tm->tm_mon)
858 + (10000u > ((
unsigned)p00_tm->tm_year + 1900u))
859 + (7u > (
unsigned)p00_tm->tm_wday)
860 + (366u > (
unsigned)p00_tm->tm_yday))
866 errno_t p00_asctime_s(
char const* p00_file,
char const* p00_context,
867 char *p00_s,
rsize_t p00_maxsize,
868 const struct tm *p00_tptr) {
881 unsigned short p00_val = 1900u + p00_tptr->tm_year;
882 if (1000 <= p00_val && p00_val <= 9999) {
883 char p00_year[6] =
"XXXX";
884 snprintf(p00_year, 6,
"%4hu", p00_val);
885 char const p00_wday[7][3] = {
886 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
888 char const p00_mon[12][3] = {
889 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
890 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
894 "%.3s %.3s %2d %.2d:%.2d:%.2d %.4s\n",
895 p00_wday[p00_tptr->tm_wday],
896 p00_mon[p00_tptr->tm_mon],
907 if (p00_s && p00_maxsize) p00_s[0] = 0;
908 p00_constraint_call(p00_ret, p00_file, p00_context,
"asctime_s runtime constraint violation");
914 #define asctime_s(...) p00_asctime_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
917 struct tm* p00_localtime_s(
char const* p00_file,
char const* p00_context,
918 time_t
const * restrict p00_t,
919 struct tm * p00_tptr) {
920 struct tm * p00_ret = 0;
926 *p00_tptr = (
struct tm) {
931 double p00_diff = difftime(*p00_t, mktime(p00_tptr));
932 int64_t p00_sec = p00_diff;
933 int64_t p00_min = p00_sec/60u;
934 p00_sec -= 60u * p00_min;
935 int64_t p00_hour = p00_min/60u;
936 p00_min -= 60u * p00_hour;
937 int64_t p00_day = p00_hour/24u;
938 p00_hour -= 24u * p00_day;
939 *p00_tptr = (
struct tm) {
943 .tm_mday = p00_day + 1,
947 if (mktime(p00_tptr) == (time_t)-1) {
950 printf(
"warning, time might be before epoch:\t%s",
date);
955 p00_constraint_call(p00_err, p00_file, p00_context,
"localtime_s runtime constraint violation");
961 #define localtime_s(...) p00_localtime_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
964 struct tm* p00_gmtime_s(
char const* p00_file,
char const* p00_context,
965 time_t
const * restrict p00_t,
966 struct tm * p00_tptr) {
967 struct tm * p00_ret = 0;
976 strftime(p00_off,
sizeof p00_off,
"%z", p00_tptr);
980 long p00_min =
strtol(&p00_off[3], 0, 10);
983 long p00_hour =
strtol(p00_off, 0, 10);
985 if (p00_hour < 0L) p00_min = -p00_min;
986 p00_tptr->tm_hour -= p00_hour;
987 p00_tptr->tm_min -= p00_min;
993 p00_constraint_call(p00_err, p00_file, p00_context,
"gmtime_s runtime constraint violation");
999 #define gmtime_s(...) p00_gmtime_s(P99_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
1002 #define ctime_s(S, M, T) asctime_s((S), (M), localtime_s((T), &(struct tm){ 0 }))