From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: etags test is broken on MS-Windows Date: Thu, 21 May 2015 19:49:22 +0300 Message-ID: <83mw0x6fl9.fsf@gnu.org> References: <83y4kmdjmj.fsf@gnu.org> <555A8E62.7060700@cs.ucla.edu> <83h9r8egen.fsf@gnu.org> <83a8wz6yyc.fsf@gnu.org> Reply-To: Eli Zaretskii NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE X-Trace: ger.gmane.org 1432226987 24111 80.91.229.3 (21 May 2015 16:49:47 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 21 May 2015 16:49:47 +0000 (UTC) Cc: eggert@cs.ucla.edu, emacs-devel@gnu.org To: Francesco =?iso-8859-1?Q?Potort=EC?= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu May 21 18:49:38 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YvTf6-0002AK-MB for ged-emacs-devel@m.gmane.org; Thu, 21 May 2015 18:49:36 +0200 Original-Received: from localhost ([::1]:58637 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YvTf5-00022a-PG for ged-emacs-devel@m.gmane.org; Thu, 21 May 2015 12:49:35 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:38282) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YvTf1-00022P-Rz for emacs-devel@gnu.org; Thu, 21 May 2015 12:49:33 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YvTez-0005wo-3L for emacs-devel@gnu.org; Thu, 21 May 2015 12:49:31 -0400 Original-Received: from mtaout20.012.net.il ([80.179.55.166]:50399) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YvTey-0005wG-KD; Thu, 21 May 2015 12:49:29 -0400 Original-Received: from conversion-daemon.a-mtaout20.012.net.il by a-mtaout20.012.net.il (HyperSendmail v2007.08) id <0NOP00L00L5IV300@a-mtaout20.012.net.il>; Thu, 21 May 2015 19:49:26 +0300 (IDT) Original-Received: from HOME-C4E4A596F7 ([87.69.4.28]) by a-mtaout20.012.net.il (HyperSendmail v2007.08) with ESMTPA id <0NOP00LBTLEEQA60@a-mtaout20.012.net.il>; Thu, 21 May 2015 19:49:26 +0300 (IDT) In-reply-to: X-012-Sender: halo1@inter.net.il X-detected-operating-system: by eggs.gnu.org: Solaris 10 X-Received-From: 80.179.55.166 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:186711 Archived-At: > Date: Thu, 21 May 2015 15:24:44 +0200 > From: Francesco Potort=EC > Cc: emacs-devel@gnu.org, Paul Eggert >=20 > >f-src/entry.for,172 > > LOGICAL FUNCTION PRTPKG ^?3,75 > > ENTRY SETPRT ^?194,3866 > > ENTRY MSGSEL ^?395,8478 > > & intensity1(^?577,12231 > > character*(*) function foo(^?579,12307 > >^L > >f-src/entry.strange_suffix,172 > > LOGICAL FUNCTION PRTPKG ^?3,75 > > ENTRY SETPRT ^?194,3866 > > ENTRY MSGSEL ^?395,8478 > > & intensity1(^?577,12231 > > character*(*) function foo(^?579,12307 > >^L > >f-src/entry.strange,171 > > LOGICAL FUNCTION PRTPKG ^?2,2 > > ENTRY SETPRT ^?193,3793 > > ENTRY MSGSEL ^?394,8405 > > & intensity1(^?576,12158 > > character*(*) function foo(^?578,12234 > > > >Now, these 3 files have exactly identical contents, and the _only_ > >difference between the first 2 and the 3rd is that the latter is > >gzip-compressed. So that should be the only reason why all its li= ne > >counts are off by 1, and its byte counts are all off by 73, which = just > >happens to be the length of the first line of the (uncompressed) f= ile. >=20 > This is a bug. >=20 > >So could it be that rewinding a 'popen'-created stream doesn't wor= k > >correctly on GNU/Linux as well? If so, we will have to make chang= es > >in etags to not do that, I think, and instead reuse the already-re= ad > >stuff as needed. >=20 > It could well be. It may have happened that, when I checked that t= he > TAGS files were the same, I just looked at them without running dif= f and > I missed this discrepancy. After thinking a bit about the alternative solution, I concluded that the simplest will be to decompress to a temporary file and read from there. Does the patch below look OK? Or can someone think about a more elegant way of solving this? diff --git a/lib-src/etags.c b/lib-src/etags.c index 0a308c1..28729da 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -116,6 +116,7 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED= TO, PROCUREMENT OF # undef HAVE_NTGUI # undef DOS_NT # define DOS_NT +# define O_CLOEXEC O_NOINHERIT #endif /* WINDOWSNT */ =20 #include @@ -125,6 +126,7 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED= TO, PROCUREMENT OF #include #include #include +#include #include #include #include @@ -336,6 +338,7 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED= TO, PROCUREMENT OF static char *absolute_dirname (char *, char *); static bool filename_is_absolute (char *f); static void canonicalize_filename (char *); +static char *etags_mktmp (void); static void linebuffer_init (linebuffer *); static void linebuffer_setlen (linebuffer *, int); static void *xmalloc (size_t); @@ -1437,7 +1440,7 @@ C code are parsed as C code (use --help --lang= =3Dc --lang=3Dyacc\n\ fdesc *fdp; compressor *compr; char *compressed_name, *uncompressed_name; - char *ext, *real_name; + char *ext, *real_name, *tmp_name; int retval; =20 canonicalize_filename (file); @@ -1522,9 +1525,20 @@ C code are parsed as C code (use --help --lang= =3Dc --lang=3Dyacc\n\ } if (real_name =3D=3D compressed_name) { - char *cmd =3D concat (compr->command, " ", real_name); - inf =3D popen (cmd, "r" FOPEN_BINARY); - free (cmd); + tmp_name =3D etags_mktmp (); + if (!tmp_name) +=09inf =3D NULL; + else +=09{ +=09 char *cmd1 =3D concat (compr->command, " ", real_name); +=09 char *cmd =3D concat (cmd1, " > ", tmp_name); +=09 free (cmd1); +=09 if (system (cmd) =3D=3D -1) +=09 inf =3D NULL; +=09 else +=09 inf =3D fopen (tmp_name, "r" FOPEN_BINARY); +=09 free (cmd); +=09} } else inf =3D fopen (real_name, "r" FOPEN_BINARY); @@ -1536,10 +1550,12 @@ C code are parsed as C code (use --help --lan= g=3Dc --lang=3Dyacc\n\ =20 process_file (inf, uncompressed_name, lang); =20 + retval =3D fclose (inf); if (real_name =3D=3D compressed_name) - retval =3D pclose (inf); - else - retval =3D fclose (inf); + { + remove (tmp_name); + free (tmp_name); + } if (retval < 0) pfatal (file); =20 @@ -1707,9 +1723,6 @@ C code are parsed as C code (use --help --lang= =3Dc --lang=3Dyacc\n\ =09} } =20 - /* We rewind here, even if inf may be a pipe. We fail if the - length of the first line is longer than the pipe block size, - which is unlikely. */ rewind (inf); =20 /* Else try to guess the language given the case insensitive file = name. */ @@ -1734,8 +1747,6 @@ C code are parsed as C code (use --help --lang= =3Dc --lang=3Dyacc\n\ if (old_last_node =3D=3D last_node) =09/* No Fortran entries found. Try C. */ =09{ -=09 /* We do not tag if rewind fails. -=09 Only the file name will be recorded in the tags file. */ =09 rewind (inf); =09 curfdp->lang =3D get_language_from_langname (cplusplus ? "c++" = : "c"); =09 find_entries (inf); @@ -5015,8 +5026,6 @@ enum,=09=090,=09=09=09st_C_enum TEX_opgrp =3D '<'; TEX_clgrp =3D '>'; } - /* If the input file is compressed, inf is a pipe, and rewind may = fail. - No attempt is made to correct the situation. */ rewind (inf); } =20 @@ -6344,6 +6353,51 @@ enum,=09=090,=09=09=09st_C_enum return path; } =20 +/* Return a newly allocated string containing a name of a temporary = file. */ +static char * +etags_mktmp (void) +{ + const char *tmpdir =3D getenv ("TMPDIR"); + const char *slash =3D "/"; + +#if MSDOS || defined (DOS_NT) + if (!tmpdir) + tmpdir =3D getenv ("TEMP"); + if (!tmpdir) + tmpdir =3D getenv ("TMP"); + if (!tmpdir) + tmpdir =3D "."; + if (tmpdir[strlen (tmpdir) - 1] =3D=3D '/' + || tmpdir[strlen (tmpdir) - 1] =3D=3D '\\') + slash =3D ""; +#else + if (!tmpdir) + tmpdir =3D "/tmp"; + if (tmpdir[strlen (tmpdir) - 1] =3D=3D '/') + slash =3D ""; +#endif + + char *templt =3D concat (tmpdir, slash, "etXXXXXX"); + int fd =3D mkostemp (templt, O_CLOEXEC); + if (fd < 0) + { + free (templt); + templt =3D NULL; + } + else + close (fd); + +#if defined (DOS_NT) + /* The file name will be used in shell redirection, so it needs to= have + DOS-style backslashes, or else the Windows shell will barf. */ + char *p; + for (p =3D templt; *p; p++) + if (*p =3D=3D '/') + *p =3D '\\'; +#endif + return templt; +} + /* Return a newly allocated string containing the file name of FILE relative to the absolute directory DIR (which should end with a s= lash). */ static char *