<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0cm;
        mso-margin-bottom-alt:auto;
        margin-left:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Hello Paul,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">unfortunately, we allow our customers to download latest iana source at the customer site during installation of our product and as a result the only requirement we have is Visual Studio compiler. 
 MinGW is an extra requirement which is not native to Windows and complicates the setup as well as impacts usability of our product.  I am afraid nmake is a requirement for our adoption of iana.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">We did more research on the topic and found a way that we can make 1 makefile work if we redefine a number of variables including some scripts (shell/batch code) in tools.ini for Visual Studio compiler
 and tools.gcc for gcc compiler and then reference these variables in Makefile, each compiler type will load their own compiler specific file with variables and all the variables will need to be parameterized in 1 platform independent makefile. 
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Alternatively, we can keep the two separate makefiles, it’s pretty common to have two separate makefiles to support both Unix-based and Windows based compilers.  Visual Studio/nmake are very popular
 on Windows, having support for nmake is likely to be beneficial to the adoption of iana on Windows and enhance iana community by adding a big group of developers using Visual Studio in their application development.    
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Regarding the Nameslashdot change on Windows stat() behaves differently. It always returns 0 when run on a filename with /. appended.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">So the assumption that if the return value is 0 the path is a directory does not hold true.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Also Windows does not define S_ISDIR, but S_IFDIR and S_IFMT so I suggest this change:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">@@ -987,6 +987,9 @@ itsdir(char const *name)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">#ifdef S_ISDIR<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">        if (res == 0)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">                return S_ISDIR(st.st_mode) != 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">+#elif defined(S_IFDIR) && defined (S_IFMT)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">+       if (res == 0)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">+               return ((st.st_mode & S_IFMT) == S_IFDIR) !=0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">#endif<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">        if (res == 0 || errno == EOVERFLOW) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">                </span>
<span lang="DE" style="mso-fareast-language:EN-US">size_t n = strlen(name);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="DE" style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">The new -DHAVE_STRTOLL=0 flag works well.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">I will investigate the other points you raised.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Thanks!<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Manuela Friedrich<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US">From:</span></b><span lang="EN-US"> Paul Eggert [mailto:eggert@cs.ucla.edu]
<br>
<b>Sent:</b> Samstag, 27. Januar 2018 04:04<br>
<b>To:</b> Manuela Friedrich <Manuela.Friedrich@actian.com>; Time Zone Mailing List <tz@iana.org><br>
<b>Subject:</b> Re: [tz] [PATCH] Support building zic.exe and zdump.exe natively on Windows with Visual Studio nmake.<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">Thanks for sending us that. However, I'd like the source code to be kept
<br>
as POSIX-like as possible, to simplify maintenance, so I'd rather not <br>
add a lot of #ifdefs in the code proper.<br>
<br>
Can you use MinGW for the port instead? That should make maintenance <br>
considerably simpler, since MinGW supports things like 'getopt' so we <br>
wouldn't have to supply our own implementation. My impression is that <br>
MinGW would avoid the need for many of the #ifdefs. See:<br>
<br>
<a href="http://www.mingw.org/">http://www.mingw.org/</a><br>
<br>
On 01/25/2018 01:31 AM, Manuela Friedrich wrote:<br>
> In localtime.c use native localtime(), gmtime(), ctime() and mktime().<br>
Why? localtime.c should be implementing localtime, not using the <br>
MS-Windows-supplied localtime.<br>
<br>
> Also use int or __int64 respectively for ssize_t type and check for Windows drive letters in tzloadbody().<br>
<br>
For something like that how about just compiling with -Dssize_t=long. <br>
That should be good enough for MS-Windows and will mean we don't need to <br>
change the .c files.<br>
<br>
> In private.h and zdump.c define strotimax depending on Visual Studio version.<br>
> It needs to be strtol for up to VS 2010 and stroll for higher versions.<br>
<br>
tzcode configures this sort of thing with CFLAGS in the makefile. I <br>
applied the attached patch to the tz development version on GitHub <br>
<<a href="https://github.com/eggert/tz">https://github.com/eggert/tz</a>>. So you should be able to build with
<br>
-DHAVE_STRTOLL=0 on older MS-Windows platforms.<br>
<br>
> In zdump.c need prototype for gmtime_r() to suffice return type requirements.<br>
> Also use __time64_t variables on Windows instead of time_t.<br>
> In main() variable declarations had to be moved to the top to avoid compile errors.<br>
<br>
I hope this is handled better in MinGW so that we don't have to worry <br>
about redeclaring gmtime_r or using __time64_t instead of time_t. If <br>
not, then this is better handled in private.h, which already does this <br>
sort of thing.<br>
<br>
> In zic.c dolink() need to have an extra mkdirs() call for Windows as we don't have link support here and the previous mkdirs() calls wouldn't have been called therefore.<br>
<br>
Thanks, I put that into the attached patch too.<br>
<br>
> Also itsdir() needs separate Windows part to check for directory flag as the namesslashdot Linux alternative alway returns directory on Windows.<br>
<br>
Could you explain what goes wrong with namesslashdot on MS-Windows? I <br>
don't see the bug here. nameslashdot tests whether a file F is a <br>
directory by statting "F/.". Why doesn't this approach work on MS-Windows?<br>
<br>
> Add nmake specific Makefile.nmake based on existing Makefile.<br>
<br>
I hope MinGW makes this unnecessary.<br>
> @@ -401,6 +409,13 @@ tzloadbody(char const *name, struct state *sp, bool doextend,<br>
> if (name[0] == ':')<br>
> ++name;<br>
> doaccess = name[0] == '/';<br>
> +#ifdef _WIN32<br>
> + /*<br>
> + ** DOS drive specifier?<br>
> + */<br>
> + if (isalpha(name[0]) && name[1]==':' && name[2] == '\\')<br>
> + doaccess = true;<br>
> +#endif<br>
> if (!doaccess) {<br>
> size_t namelen = strlen(name);<br>
> if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)<br>
<br>
This change should not be needed, as there's no need to support absolute <br>
file names as TZ specifiers under MS-Windows. (Even if we did, the above <br>
code would not work on some MS-Windows variants; it's better to avoid <br>
this messy situation.)<br>
> diff --git a/zdump.c b/zdump.c<br>
> index 60a027e..fc90662 100644<br>
> --- a/zdump.c<br>
> +++ b/zdump.c<br>
> @@ -4,6 +4,9 @@<br>
> */<br>
> <br>
> #include "version.h"<br>
> +#ifdef _WIN32<br>
> +#include <stdlib.h><br>
> +#endif<br>
<br>
I don't see why this is needed, as private.h includes stdlib.h.<br>
<br>
> + struct tm * newtmp;<br>
> bool iflag = false;<br>
> + bool newtm_ok;<br>
> <br>
> cutlotime = absolute_min_time;<br>
> cuthitime = absolute_max_time;<br>
> @@ -531,7 +563,6 @@ main(int argc, char *argv[])<br>
> for (i = optind; i < argc; ++i) {<br>
> timezone_t tz = tzalloc(argv[i]);<br>
> char const *ab;<br>
> - time_t t;<br>
> struct tm tm, newtm;<br>
> bool tm_ok;<br>
> if (!tz) {<br>
> @@ -562,12 +593,12 @@ main(int argc, char *argv[])<br>
> }<br>
> }<br>
> while (t < cuthitime) {<br>
> - time_t newt = ((t < absolute_max_time - SECSPERDAY / 2<br>
> + newt = ((t < absolute_max_time - SECSPERDAY / 2<br>
> && t + SECSPERDAY / 2 < cuthitime)<br>
> ? t + SECSPERDAY / 2<br>
> : cuthitime);<br>
> - struct tm *newtmp = localtime_rz(tz, &newt, &newtm);<br>
> - bool newtm_ok = newtmp != NULL;<br>
> + newtmp = localtime_rz(tz, &newt, &newtm);<br>
> + newtm_ok = newtmp != NULL;<br>
> if (tm_ok != newtm_ok<br>
> || (tm_ok && (delta(&newtm, &tm) != newt - t<br>
> || newtm.tm_isdst != tm.tm_isdst<br>
<br>
I don't see why these changes are needed, as the code is valid C89 code <br>
without them.<o:p></o:p></p>
</div>
</body>
</html>