Rev 18 | Rev 23 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 18 | Rev 19 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | #endif // !thread_local |
22 | #endif // !thread_local |
23 | 23 | ||
24 | 24 | ||
25 | // Microsoft-specific shims |
25 | // Microsoft-specific shims |
26 | #ifdef _MSC_VER |
26 | #ifdef _MSC_VER |
- | 27 | #include <stdarg.h> |
|
- | 28 | #include <io.h> |
|
- | 29 | #include <direct.h> |
|
27 | #if defined(_M_AMD64) |
30 | #if defined(_M_AMD64) |
28 | #define __x86_64__ 1 |
31 | #define __x86_64__ 1 |
29 | #elif defined(_M_ARM64) || defined(_M_ARM64EC) |
32 | #elif defined(_M_ARM64) || defined(_M_ARM64EC) |
30 | #define __aarch64__ 1 |
33 | #define __aarch64__ 1 |
31 | #endif // native platform identification |
34 | #endif // native platform identification |
Line 35... | Line 38... | ||
35 | #define getenv(v) sane_getenv ((v)) // STFU Microsoft |
38 | #define getenv(v) sane_getenv ((v)) // STFU Microsoft |
36 | static struct tm *sane_localtime (const time_t *clock) { thread_local static struct tm localtime_tm; if (localtime_s (&localtime_tm, clock) != 0) return (NULL); return (&localtime_tm); } // non-complaining localtime() implementation for MSVC. Uses TLS. |
39 | static struct tm *sane_localtime (const time_t *clock) { thread_local static struct tm localtime_tm; if (localtime_s (&localtime_tm, clock) != 0) return (NULL); return (&localtime_tm); } // non-complaining localtime() implementation for MSVC. Uses TLS. |
37 | #define localtime(t) sane_localtime ((t)) // STFU Microsoft |
40 | #define localtime(t) sane_localtime ((t)) // STFU Microsoft |
38 | static inline char *sane_asctime (const struct tm *tm_time) { thread_local static char asctimestr[64]; if (asctime_s (asctimestr, sizeof (asctimestr), tm_time) != 0) return (NULL); return (asctimestr); } // non-complaining asctime() implementation for MSVC. Uses TLS. |
41 | static inline char *sane_asctime (const struct tm *tm_time) { thread_local static char asctimestr[64]; if (asctime_s (asctimestr, sizeof (asctimestr), tm_time) != 0) return (NULL); return (asctimestr); } // non-complaining asctime() implementation for MSVC. Uses TLS. |
39 | #define asctime(t) sane_asctime ((t)) // STFU Microsoft |
42 | #define asctime(t) sane_asctime ((t)) // STFU Microsoft |
- | 43 | static inline int vasprintf (char **out_string, const char *fmt, va_list va_args) { int retval; va_list ap; va_copy (ap, va_args); retval = _vsnprintf_s (NULL, 0, 0, fmt, ap); va_end (ap); if (retval == -1) return (-1); *out_string = malloc ((size_t) retval + 1); if (*out_string == NULL) return (-1); va_copy (ap, va_args); retval = _vsnprintf_s (*out_string, (size_t) retval + 1, (size_t) retval + 1, fmt, va_args); va_end (ap); return (retval); } // vasprintf() implementation for Windows |
|
- | 44 | static inline int asprintf (char **out_string, const char *fmt, ...) { int r; va_list ap; va_start (ap, fmt); r = vasprintf (out_string, fmt, ap); va_end (ap); return (r); } // asprintf() implementation for Windows |
|
- | 45 | #define strcasecmp(s1,s2) _stricmp ((s1), (s2)) |
|
- | 46 | #define __builtin_bswap16(x) _byteswap_ushort ((unsigned short) (x)) |
|
- | 47 | #define __builtin_bswap32(x) _byteswap_ulong ((unsigned long) (x)) |
|
- | 48 | #define __ORDER_LITTLE_ENDIAN__ 1234 |
|
- | 49 | #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ // all Windows machines are little-endian |
|
40 | #define S_IFIFO 0x1000 |
50 | #define S_IFIFO 0x1000 |
41 | #define S_IFLNK 0xa000 |
51 | #define S_IFLNK 0xa000 |
42 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
52 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
43 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
53 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
44 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) |
54 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) |
45 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) |
55 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) |
- | 56 | #define major(rdev) ((int) (((rdev) >> 10) & 0x3f)) // on Windows assume a QNX-compatible makedev(). Node is zero (local host). |
|
- | 57 | #define minor(rdev) ((int) (((rdev) >> 0) & 0x3ff)) // on Windows assume a QNX-compatible makedev(). Node is zero (local host). |
|
- | 58 | #define makedev(maj,min) ((dev_t) (((maj) << 10) | (min))) // on Windows assume a QNX-compatible makedev(). Node is zero (local host). |
|
46 | #define strdup(s) _strdup ((s)) |
59 | #define strdup(s) _strdup ((s)) |
47 | #define strcasecmp(s1,s2) _stricmp ((s1), (s2)) |
60 | #define strcasecmp(s1,s2) _stricmp ((s1), (s2)) |
48 | #define strtok_r(s,delim,ctx) strtok_s ((s), (delim), (ctx)) |
61 | #define strtok_r(s,delim,ctx) strtok_s ((s), (delim), (ctx)) |
49 | #define mkdir( |
62 | #define mkdir(pathname,mode) _mkdir ((pathname)) |
50 | #define utimbuf __utimbuf32 |
63 | #define utimbuf __utimbuf32 |
51 | #define utime(p,t) _utime32 ((p), (t)) |
64 | #define utime(p,t) _utime32 ((p), (t)) |
52 | #define access( |
65 | #define access(pathname,accmode) _access ((pathname), (accmode)) |
- | 66 | #define unlink(pathname) _unlink ((pathname)) |
|
- | 67 | #define ftello(fp) _ftelli64 ((fp)) |
|
- | 68 | #define fileno(fp) _fileno ((fp)) |
|
- | 69 | #define ftruncate(fd,size) _chsize_s ((fd), (size)) |
|
- | 70 | #define readlink(pathname,buf,maxsize) ((*_errno () = 129 /*ENOTSUP*/), -1) // readlink() not supported on Windows |
|
- | 71 | #define stat _stat64 |
|
- | 72 | #define getcwd(buf,maxsize) _getcwd ((buf), (maxsize)) |
|
- | 73 | #define chdir(pathname) _chdir ((pathname)) |
|
- | 74 | #define putenv(v) _putenv ((v)) |
|
53 | #define MAXPATHLEN 1024 |
75 | #define MAXPATHLEN 1024 |
- | 76 | struct dirent { unsigned char d_namlen; char *d_name; }; // bring struct dirent/opendir() support to Windows |
|
- | 77 | typedef struct DIR { intptr_t handle; struct __finddata64_t info; struct dirent result; char *pathname; char *search_pattern; } DIR; |
|
- | 78 | static inline DIR *opendir (const char *name) // UNIX-like opendir() implementation for Windows |
|
- | 79 | { |
|
- | 80 | DIR *dir; size_t base_length, all_length; const char *suffix; |
|
- | 81 | dir = (DIR *) malloc (sizeof (DIR)); if (dir == NULL) { /*errno already set*/ return (NULL); } |
|
- | 82 | dir->pathname = _fullpath (NULL, name, 0); // system will mallocate, caller frees |
|
- | 83 | if (dir->pathname == NULL) { free (dir); *_errno () = 12 /*ENOMEM*/; return (NULL); } |
|
- | 84 | base_length = strlen (name); |
|
- | 85 | suffix = ((name[base_length - 1] == '\\') || (name[base_length - 1] == '/') ? "*" : "/*"); // search pattern must end with suitable wildcard |
|
- | 86 | all_length = base_length + strlen (suffix) + 1; |
|
- | 87 | dir->search_pattern = (char *) malloc (all_length); if (dir->search_pattern == NULL) { free (dir->pathname); free (dir); *_errno () = 12 /*ENOMEM*/; return (NULL); } |
|
- | 88 | strcpy_s (dir->search_pattern, all_length, name); strcat_s (dir->search_pattern, all_length, suffix); |
|
- | 89 | dir->handle = _findfirst64 (dir->search_pattern, &dir->info); if (dir->handle == -1) { free (dir->search_pattern); free (dir->pathname); free (dir); return (NULL); } |
|
- | 90 | dir->result.d_namlen = 0; dir->result.d_name = NULL; // first-time initialization |
|
- | 91 | return (dir); |
|
- | 92 | } |
|
- | 93 | static inline int closedir (DIR *dir) // UNIX-like closedir() implementation for Windows |
|
- | 94 | { |
|
- | 95 | int result = -1; |
|
- | 96 | if (dir == NULL) { *_errno () = 9 /*EBADF*/; return (-1); } |
|
- | 97 | if (dir->handle != -1) result = _findclose (dir->handle); |
|
- | 98 | if (dir->search_pattern != NULL) free (dir->search_pattern); |
|
- | 99 | if (dir->pathname != NULL) free (dir->pathname); |
|
- | 100 | free (dir); |
|
- | 101 | if (result == -1) *_errno () = 9 /*EBADF*/; // map all errors to EBADF |
|
- | 102 | return (result); |
|
- | 103 | } |
|
- | 104 | static inline struct dirent *readdir (DIR *dir) // UNIX-like readdir() implementation for Windows |
|
- | 105 | { |
|
- | 106 | struct dirent *result = NULL; |
|
- | 107 | if ((dir == NULL) || (dir->handle == -1)) { *_errno () = 9 /*EBADF*/; return (NULL); } |
|
- | 108 | if ((dir->result.d_name == NULL) || (_findnext64 (dir->handle, &dir->info) != -1)) { |
|
- | 109 | result = &dir->result; |
|
- | 110 | result->d_name = dir->info.name; |
|
- | 111 | result->d_namlen = (unsigned char) strlen (dir->info.name); |
|
- | 112 | } |
|
- | 113 | return (result); |
|
- | 114 | } |
|
- | 115 | static inline void rewinddir (DIR *dir) // UNIX-like rewinddir() implementation for Windows |
|
- | 116 | { |
|
- | 117 | if ((dir == NULL) || (dir->handle == -1)) { *_errno () = 9 /*EBADF*/; return; } |
|
- | 118 | _findclose (dir->handle); |
|
- | 119 | dir->handle = (long) _findfirst64 (dir->search_pattern, &dir->info); |
|
- | 120 | dir->result.d_namlen = 0; dir->result.d_name = NULL; // first-time initialization |
|
- | 121 | } |
|
54 | #else // !_MSC_VER |
122 | #else // !_MSC_VER |
55 | #define strcpy_s(s1,s1size,s2) strcpy ((s1), (s2)) |
123 | #define strcpy_s(s1,s1size,s2) strcpy ((s1), (s2)) |
56 | #define strcat_s(s1,s1size,s2) strcat ((s1), (s2)) |
124 | #define strcat_s(s1,s1size,s2) strcat ((s1), (s2)) |
57 | #define sprintf_s(s1,s1size,...) sprintf ((s1), __VA_ARGS__) |
125 | #define sprintf_s(s1,s1size,...) sprintf ((s1), __VA_ARGS__) |
58 | #define fopen_s(fp,pathname,mode) *(fp) = fopen ((pathname), (mode)) |
126 | #define fopen_s(fp,pathname,mode) *(fp) = fopen ((pathname), (mode)) |