From d34159fb9e8bfa32bb20998f6265dd62e4bf4584 Mon Sep 17 00:00:00 2001 From: bulk88 Date: Wed, 8 May 2024 03:30:19 -0400 Subject: [PATCH] restore Visual C 6 and newer but older VC 200X builds -remove mixed declarations and code -abstract quads/long long/int64_t type -in w32err.c in map_windows32_error_to_string() switch from the inefficient wsprintf() to snprintf(), wsprintf is really wsprintfA from user32.dll, and map_windows32_error_to_string:wsprintf was the ONLY linking dependency of mingw gnumake and visual c gnumake to user32.dll. user32 is a GUI library, and a bit illogical to load over and over on process start up for the short running and high process start frequency gnumake, there is startup CPU overhead, disk/FS I/O and permanently allocated private memory pages overhead (C RW globals in each DLL) for every dll. This is an optimization, for process start up speed. map_windows32_error_to_string:wsprintf code git blames to SHA-1: e7a525c5d53029de18871890196b665c803e98d3 * Wed May 15 10:14:14 CDT 1996 Rob Tulloh * w32/subproc/w32err.c: WIN32: subproc library support code which is initial commit of w32err.c --- src/config.h.W32 | 8 ++- src/dir.c | 4 +- src/function.c | 12 ++-- src/job.c | 3 +- src/main.c | 6 +- src/makeint.h | 37 +++++++++- src/misc.c | 4 +- src/posixos.c | 2 +- src/remake.c | 46 ++++++++++--- src/variable.c | 2 +- src/variable.h | 2 +- src/w32/include/dirent.h | 5 ++ src/w32/subproc/sub_proc.c | 26 +++---- src/w32/subproc/w32err.c | 2 +- src/w32/w32os.c | 138 +++++++++++++++++++++++++++++++++++-- src/warning.c | 12 ++-- 16 files changed, 257 insertions(+), 52 deletions(-) diff --git a/src/config.h.W32 b/src/config.h.W32 index 7dbe2ab0..375aed7d 100644 --- a/src/config.h.W32 +++ b/src/config.h.W32 @@ -23,7 +23,9 @@ this program. If not, see . */ /* Suppress some Visual C++ warnings. Maybe after the code cleanup for ISO C we can remove some/all of these. */ #if _MSC_VER > 1000 +# pragma warning(disable:4091) /* ignored on left of ‘MyEnum’ when no variable is declared*/ # pragma warning(disable:4100) /* unreferenced formal parameter */ +# pragma warning(disable:4127) /* conditional expression is constant "while(1)" */ # pragma warning(disable:4130) /* logical operation on address of string constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ @@ -342,7 +344,7 @@ this program. If not, see . */ /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 -#ifdef __TINYC__ +#if defined (__TINYC__) || (defined(_MSC_VER) && _MSC_VER < 1800) # ifndef strtoll # define strtoll _strtoi64 # endif @@ -576,8 +578,8 @@ char *ttyname (int); /* Define {u,}intmax_t if not defined in or . */ #if !HAVE_STDINT_H && !HAVE_INTTYPES_H -#define intmax_t long long -#define uintmax_t unsigned long long +#define intmax_t __int64 +#define uintmax_t unsigned __int64 #endif /* Define if you have that is POSIX.1 compatible. */ diff --git a/src/dir.c b/src/dir.c index a805a377..21ab41af 100644 --- a/src/dir.c +++ b/src/dir.c @@ -1106,7 +1106,7 @@ print_dir_data_base (void) #if MK_OS_W32 printf (_("# %s (key %s, mtime %s): could not be opened.\n"), dir->name, dir->contents->path_key, - make_ulltoa ((unsigned long long)dir->contents->mtime, buf)); + make_ulltoa ((unsigned _quad_t)dir->contents->mtime, buf)); #elif defined(VMS_INO_T) printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), dir->name, dir->contents->dev, @@ -1139,7 +1139,7 @@ print_dir_data_base (void) #if MK_OS_W32 printf (_("# %s (key %s, mtime %s): "), dir->name, dir->contents->path_key, - make_ulltoa ((unsigned long long)dir->contents->mtime, buf)); + make_ulltoa ((unsigned _quad_t)dir->contents->mtime, buf)); #elif defined(VMS_INO_T) printf (_("# %s (device %d, inode [%d,%d,%d]): "), dir->name, dir->contents->dev, diff --git a/src/function.c b/src/function.c index 82a9fe26..c1f5b6b6 100644 --- a/src/function.c +++ b/src/function.c @@ -758,13 +758,13 @@ strip_whitespace (const char **begpp, const char **endpp) return (char *)*begpp; } -static long long +static _quad_t parse_numeric (const char *s, const char *msg) { const char *beg = s; const char *end = s + strlen (s) - 1; char *endp; - long long num; + _quad_t num; strip_whitespace (&beg, &end); if (beg > end) @@ -786,7 +786,7 @@ func_word (char *o, char **argv, const char *funcname UNUSED) { const char *end_p; const char *p; - long long i; + _quad_t i; i = parse_numeric (argv[0], _("invalid first argument to 'word' function")); @@ -809,7 +809,7 @@ static char * func_wordlist (char *o, char **argv, const char *funcname UNUSED) { char buf[INTSTR_LENGTH + 1]; - long long start, stop, count; + _quad_t start, stop, count; const char* badfirst = _("invalid first argument to 'wordlist' function"); const char* badsecond = _("invalid second argument to 'wordlist' function"); @@ -1723,10 +1723,10 @@ windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, *pid_p = (pid_t) hProcess; /* set up to read data from child */ - pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY); + pipedes[0] = _open_osfhandle ((INT_PTR) hChildOutRd, O_RDONLY); /* this will be closed almost right away */ - pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND); + pipedes[1] = _open_osfhandle ((INT_PTR) hChildOutWr, O_APPEND); return 0; } else diff --git a/src/job.c b/src/job.c index 09fe9d16..c0654cfb 100644 --- a/src/job.c +++ b/src/job.c @@ -22,6 +22,7 @@ this program. If not, see . */ /* Default shell to use. */ #if MK_OS_W32 # include +# include /* for WSABASEERR */ const char *default_shell = "sh.exe"; int no_default_sh_exe = 1; @@ -346,7 +347,7 @@ create_batch_file (char const *base, int unixy, int *fd) const unsigned final_size = path_size + size + 1; char *const path = xmalloc (final_size); memcpy (path, temp_path, final_size); - *fd = _open_osfhandle ((intptr_t)h, 0); + *fd = _open_osfhandle ((INT_PTR)h, 0); if (unixy) { char *p; diff --git a/src/main.c b/src/main.c index 15104212..36bd5cec 100644 --- a/src/main.c +++ b/src/main.c @@ -3360,9 +3360,11 @@ decode_switches (int argc, const char **argv, enum variable_origin origin) warn_undefined_variables_flag = 0; } - if (warn_flags) - for (const char **pp = warn_flags->list; *pp; ++pp) + if (warn_flags) { + const char **pp; + for (pp = warn_flags->list; *pp; ++pp) decode_warn_actions (*pp, NULL); + } /* Perform any special switch handling. */ run_silent = silent_flag; diff --git a/src/makeint.h b/src/makeint.h index 5a553093..3d8812e9 100644 --- a/src/makeint.h +++ b/src/makeint.h @@ -292,9 +292,13 @@ char *strerror (int errnum); #if defined _MSC_VER || defined __MINGW32__ # define MK_PRI64_PREFIX "I64" +# define _quad_t __int64 #else # define MK_PRI64_PREFIX "ll" #endif +#ifndef _quad_t +# define _quad_t long long +#endif #ifndef PRIdMAX # define PRIdMAX MK_PRI64_PREFIX "d" #endif @@ -306,6 +310,35 @@ char *strerror (int errnum); #endif #define FILE_TIMESTAMP uintmax_t +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) +//must use shim on all < VC 2015 s +// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/snprintf-snprintf-snprintf-l-snwprintf-snwprintf-l?view=msvc-170 +#define snprintf _snprintf_c99 + +int _snprintf_c99( + char * dest, + size_t count, + const char * format, + ...); + +#endif + + +#define HAVE_STRTOLL 1 +#if defined (__TINYC__) || (defined(_MSC_VER) && _MSC_VER < 1800) +# ifndef strtoll +# define strtoll _strtoi64 +# endif +# ifndef strtoull +# define strtoull _strtoui64 +# endif +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1300) +# define _strtoi64 _strtoi64_vc +__int64 _strtoi64_vc(const char *nptr, char **endptr, int base); +#endif + #if !defined(HAVE_STRSIGNAL) char *strsignal (int signum); #endif @@ -583,8 +616,8 @@ void pfatal_with_name (const char *) NORETURN; void perror_with_name (const char *, const char *); #define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s)) unsigned int make_toui (const char*, const char**); -char *make_lltoa (long long, char *); -char *make_ulltoa (unsigned long long, char *); +char *make_lltoa (_quad_t, char *); +char *make_ulltoa (unsigned _quad_t, char *); void make_seed (unsigned int); unsigned int make_rand (void); pid_t make_pid (void); diff --git a/src/misc.c b/src/misc.c index a53301df..09ddfbf4 100644 --- a/src/misc.c +++ b/src/misc.c @@ -63,14 +63,14 @@ make_toui (const char *str, const char **error) We can't use standard PRI* here: those are based on intNN_t types. */ char * -make_lltoa (long long val, char *buf) +make_lltoa (_quad_t val, char *buf) { sprintf (buf, "%" MK_PRI64_PREFIX "d", val); return buf; } char * -make_ulltoa (unsigned long long val, char *buf) +make_ulltoa (unsigned _quad_t val, char *buf) { sprintf (buf, "%" MK_PRI64_PREFIX "u", val); return buf; diff --git a/src/posixos.c b/src/posixos.c index 6b0b716e..d4650007 100644 --- a/src/posixos.c +++ b/src/posixos.c @@ -160,7 +160,7 @@ jobserver_setup (int slots, const char *style) fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX) + INTSTR_LENGTH + 2); sprintf (fifo_name, "%s/" FNAME_PREFIX "%03" MK_PRI64_PREFIX "d", - tmpdir, (long long)make_pid ()); + tmpdir, (_quad_t)make_pid ()); EINTRLOOP (r, mkfifo (fifo_name, 0600)); if (r < 0) diff --git a/src/remake.c b/src/remake.c index ee8971e7..259614f3 100644 --- a/src/remake.c +++ b/src/remake.c @@ -33,16 +33,42 @@ this program. If not, see . */ #if MK_OS_VMS #include #endif + #if MK_OS_W32 #include #include #include -#if defined(_MSC_VER) && _MSC_VER > 1200 + +# if defined(_MSC_VER) +# if MSC_VER > 1200 /* VC7 or later supports _stat64 to access 64-bit file size. */ -#define STAT _stat64 -#else -#define STAT stat -#endif +# define STAT _stat64 +# define U64_TO_DBL_VC(u64) ((double)(u64)) +# else +/* is VC 6*/ +# define STAT stat +/* Old MS compilers do not implement the double->uint64 conversion and + * silently do a double->int64 conversion instead. See + * http://connect.microsoft.com/VisualStudio/feedback/details/270762/error-in-converting-double-to-unsigned-long-long */ +# define U64_TO_DBL_VC(nv) u64_to_dbl_vc(nv) + +/* don't trust atof, so generate 2**-32 from simpler constants and + * hope the VC optimizer will do its work properly */ + + +#define DBL_0x1p16 ((double)65536) +#define DBL_0x1p32 (DBL_0x1p16 * DBL_0x1p16) + static double + u64_to_dbl_vc(unsigned __int64 u64) { + unsigned long h = u64 >> 32; + unsigned long l = u64 & 0xffffffff; + return (DBL_0x1p32 * h) + (double)l; + } +# endif +/* Win32 but not VC */ +# else +# define U64_TO_DBL_VC(u64) ((double)(u64)) +# endif #endif @@ -1526,9 +1552,13 @@ f_mtime (struct file *file, int search) if (adjusted_now < adjusted_mtime) { double from_now = - (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now) - + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now)) - / 1e9)); + U64_TO_DBL_VC(( + FILE_TIMESTAMP_S (mtime) + - FILE_TIMESTAMP_S (now) + + (FILE_TIMESTAMP)(( + (FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now)) / 1e9 + )) + )); char from_now_string[100]; if (from_now >= 100.0 && from_now < (double) ULONG_MAX) diff --git a/src/variable.c b/src/variable.c index af3d6a40..f5a25d27 100644 --- a/src/variable.c +++ b/src/variable.c @@ -33,7 +33,7 @@ this program. If not, see . */ #include "warning.h" /* Incremented every time we enter target_environment(). */ -unsigned long long env_recursion = 0; +unsigned _quad_t env_recursion = 0; /* Incremented every time we add or remove a global variable. */ static unsigned long variable_changenum = 0; diff --git a/src/variable.h b/src/variable.h index 9cedebcd..291b61af 100644 --- a/src/variable.h +++ b/src/variable.h @@ -120,7 +120,7 @@ struct pattern_var struct variable variable; }; -extern unsigned long long env_recursion; +extern unsigned _quad_t env_recursion; extern char *variable_buffer; extern struct variable_set_list *current_variable_set_list; extern struct variable *default_goal_var; diff --git a/src/w32/include/dirent.h b/src/w32/include/dirent.h index 0de53970..1dd467d9 100644 --- a/src/w32/include/dirent.h +++ b/src/w32/include/dirent.h @@ -27,6 +27,11 @@ this program. If not, see . */ #include #include +/* missing in VC 6 */ +#ifndef FILE_ATTRIBUTE_DEVICE +# define FILE_ATTRIBUTE_DEVICE 64 +#endif + #ifndef NAME_MAX #define NAME_MAX 255 #endif diff --git a/src/w32/subproc/sub_proc.c b/src/w32/subproc/sub_proc.c index ad9e2570..3dc0992e 100644 --- a/src/w32/subproc/sub_proc.c +++ b/src/w32/subproc/sub_proc.c @@ -21,7 +21,7 @@ this program. If not, see . */ #include #include /* for _get_osfhandle */ #ifdef _MSC_VER -# include /* for intptr_t */ +# include /* for INT_PTR */ #else # include #endif @@ -47,9 +47,9 @@ this program. If not, see . */ static char *make_command_line(char *shell_name, char *exec_path, char **argv); typedef struct sub_process_t { - intptr_t sv_stdin[2]; - intptr_t sv_stdout[2]; - intptr_t sv_stderr[2]; + INT_PTR sv_stdin[2]; + INT_PTR sv_stdout[2]; + INT_PTR sv_stderr[2]; int using_pipes; char *inp; DWORD incnt; @@ -436,12 +436,12 @@ process_init() pproc->lerrno = E_SCALL; return((HANDLE)pproc); } - pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; - pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; - pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; - pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; - pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; - pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; + pproc->sv_stdin[0] = (INT_PTR) stdin_pipes[0]; + pproc->sv_stdin[1] = (INT_PTR) stdin_pipes[1]; + pproc->sv_stdout[0] = (INT_PTR) stdout_pipes[0]; + pproc->sv_stdout[1] = (INT_PTR) stdout_pipes[1]; + pproc->sv_stderr[0] = (INT_PTR) stderr_pipes[0]; + pproc->sv_stderr[1] = (INT_PTR) stderr_pipes[1]; pproc->using_pipes = 1; @@ -464,9 +464,9 @@ process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) * Just pass the provided file handles to the 'child * side' of the pipe, bypassing pipes altogether. */ - pproc->sv_stdin[1] = (intptr_t) stdinh; - pproc->sv_stdout[1] = (intptr_t) stdouth; - pproc->sv_stderr[1] = (intptr_t) stderrh; + pproc->sv_stdin[1] = (INT_PTR) stdinh; + pproc->sv_stdout[1] = (INT_PTR) stdouth; + pproc->sv_stderr[1] = (INT_PTR) stderrh; pproc->last_err = pproc->lerrno = 0; } diff --git a/src/w32/subproc/w32err.c b/src/w32/subproc/w32err.c index ddcfa5d5..f5b48a89 100644 --- a/src/w32/subproc/w32err.c +++ b/src/w32/subproc/w32err.c @@ -50,7 +50,7 @@ map_windows32_error_to_string (DWORD ercode) { /* Fill message buffer with a default message in * case FormatMessage fails */ - wsprintf (szMessageBuffer, "Error %ld", ercode); + snprintf (szMessageBuffer, sizeof(szMessageBuffer)-1, "Error %ld", ercode); /* * Special code for winsock error handling. diff --git a/src/w32/w32os.c b/src/w32/w32os.c index af02621e..15e6171d 100644 --- a/src/w32/w32os.c +++ b/src/w32/w32os.c @@ -170,7 +170,7 @@ os_anontmp () NULL); /* no template file */ if (h != INVALID_HANDLE_VALUE) - return _open_osfhandle ((intptr_t)h, 0); + return _open_osfhandle ((INT_PTR)h, 0); { const DWORD er = GetLastError (); @@ -434,7 +434,7 @@ osync_get_mutex () /* Prepare the mutex handle string for our children. 2 hex digits per byte + 2 characters for "0x" + null. */ mutex = xmalloc ((2 * sizeof (osync_handle)) + 2 + 1); - sprintf (mutex, "0x%Ix", (unsigned long long)(DWORD_PTR)osync_handle); + sprintf (mutex, "0x%Ix", (DWORD_PTR)osync_handle); } return mutex; @@ -444,17 +444,21 @@ unsigned int osync_parse_mutex (const char *mutex) { char *endp; - unsigned long long i; + UINT_PTR i; errno = 0; +#if defined _WIN64 i = strtoull (mutex, &endp, 16); +#else + i = strtoul (mutex, &endp, 16); +#endif if (errno != 0) OSS (fatal, NILF, _("cannot parse output sync mutex %s: %s"), mutex, strerror (errno)); if (endp[0] != '\0') OS (fatal, NILF, _("invalid output sync mutex: %s"), mutex); - osync_handle = (HANDLE) (DWORD_PTR) i; + osync_handle = (HANDLE) i; return 1; } @@ -527,6 +531,130 @@ get_handle_for_fd (int fd) { /* This funcion call is needed to get around the "bad-function-cast"-warning emitted by GCC when casting and assigning in the same statement. */ - intptr_t fh = _get_osfhandle (fd); + INT_PTR fh = _get_osfhandle (fd); return (HANDLE) fh; } + +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) +int _snprintf_c99( + char * dest, + size_t count, + const char * format, + ...) { + va_list args; + int result; + char * get_len_buf; + + va_start(args, format); + result = _vsnprintf( + dest, + count - 1, + format, + args + ); + if (result < 0) { + dest[count] = '\0'; + get_len_buf = alloca(1024); + result = _vsnprintf(get_len_buf, 1023, format, args); + if (result >= 0 && result < 1023) { + result = strlen(get_len_buf); + } else { + /* don't bother with malloc/strlen in a loop + if this is reached, something is wrong, 1KB is enough + */ + O (fatal, NILF, _("_snprintf_c99 output too big")); + result = -1; + } + } + va_end(args); + return result; +} +#endif + + +/*VC 6 doesn't have strtoi64, VC 7/2003 does */ +#if defined(_MSC_VER) && (_MSC_VER < 1300) +/* from ReactOS /sdk/lib/crt/string/strtoi64.c + https://git.reactos.org/?p=reactos.git;a=blob;f=COPYING3;hb=HEAD +*/ +/* Based on Wine Staging 1.9.9 - dlls/msvcrt/string.c */ + +/********************************************************************* +* _strtoi64_l (MSVCRT.@) +* +*/ +__int64 _strtoi64_vc(const char *nptr, char **endptr, int base) +{ + const char *p = nptr; + BOOL negative = FALSE; + BOOL got_digit = FALSE; + __int64 ret = 0; + + + if ( + !(nptr != NULL) + || !(base == 0 || base >= 2) + || !(base <= 36) + ) { + *_errno() = EINVAL; + return 0; + } + + while (isspace(*nptr)) nptr++; + + if(*nptr == '-') { + negative = TRUE; + nptr++; + } else if(*nptr == '+') + nptr++; + + if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') { + base = 16; + nptr += 2; + } + + if(base == 0) { + if(*nptr=='0') + base = 8; + else + base = 10; + } + + while(*nptr) { + char cur = tolower(*nptr); + int v; + + if(isdigit(cur)) { + if(cur >= '0'+base) + break; + v = cur-'0'; + } else { + if(cur<'a' || cur>='a'+base-10) + break; + v = cur-'a'+10; + } + got_digit = TRUE; + + if(negative) + v = -v; + + nptr++; + + if(!negative && (ret>_I64_MAX/base || ret*base>_I64_MAX-v)) { + ret = _I64_MAX; + *_errno() = ERANGE; + } + else if (negative && (ret<_I64_MIN / base || ret*base<_I64_MIN - v)) { + ret = _I64_MIN; + *_errno() = ERANGE; + } + else + ret = ret*base + v; + } + + if(endptr) + *endptr = (char*)(got_digit ? nptr : p); + + return ret; +} +#endif diff --git a/src/warning.c b/src/warning.c index 35950f77..634137f2 100644 --- a/src/warning.c +++ b/src/warning.c @@ -44,8 +44,9 @@ static const char *w_name_map[wt_max] = { static void set_warnings () { + enum warning_type wt = 0; /* Called whenever any warnings could change; resets the current actions. */ - for (enum warning_type wt = 0; wt < wt_max; ++wt) + for (; wt < wt_max; ++wt) warnings[wt] = warn_flag.actions[wt] != w_unset ? warn_flag.actions[wt] : warn_flag.global != w_unset ? warn_flag.global @@ -73,15 +74,17 @@ warn_init () static void init_data (struct warning_data *data) { + enum warning_type wt = wt_invalid_var; data->global = w_unset; - for (enum warning_type wt = wt_invalid_var; wt < wt_max; ++wt) + for (; wt < wt_max; ++wt) data->actions[wt] = w_unset; } static enum warning_action decode_warn_action (const char *action, size_t length) { - for (enum warning_action st = w_ignore; st <= w_error; ++st) + enum warning_action st = w_ignore; + for (; st <= w_error; ++st) { size_t len = strlen (w_action_map[st]); if (length == len && strncasecmp (action, w_action_map[st], length) == 0) @@ -94,7 +97,8 @@ decode_warn_action (const char *action, size_t length) static enum warning_type decode_warn_name (const char *name, size_t length) { - for (enum warning_type wt = wt_invalid_var; wt < wt_max; ++wt) + enum warning_type wt = wt_invalid_var; + for (; wt < wt_max; ++wt) { size_t len = strlen (w_name_map[wt]); if (length == len && strncasecmp (name, w_name_map[wt], length) == 0) -- 2.35.1.windows.2