bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: new module: relpath


From: Eli Zaretskii
Subject: Re: new module: relpath
Date: Mon, 18 Jun 2012 18:30:20 +0300

> From: Akim Demaille <address@hidden>
> Date: Thu, 14 Jun 2012 18:02:35 +0200
> 
> In Bison, I consider computing relative paths between files
> (one concrete use is when the user creates the parser implementation
> file in --output=sub1/sub2/parser.c and the header file in
> --defines=sub3/sub4/parser.h, in which case parser.c should include
> "../../sub3/sub4/parser.h").
> 
> At least to experiment on the concept, and on a suggestion from
> Eric Blake weeks ago, I stole bits of the coreutils, and made them
> a gnulib module.

Perhaps the comments below, mainly related to portability to
MS-Windows (but not only that) will be helpful, even though a lot has
been said already.

> +  /* We already know path1[0] and path2[0] are '/'.  Special case
> +     '//', which is only present in a canonical name on platforms
> +     where it is distinct.  */

This should take into account the drive letter on MS-Windows.  (I
suggest to use FILE_SYSTEM_PREFIX from dosname.h for this.)  It should
also detect that the drive letters are different and return zero.
Finally, there's the issue of whether "d:/foo/bar" and "/foo/baz"
should return a non-zero value (these inputs are possible because
'relpath' does not require the arguments to be canonicalized; perhaps
it should, see below).

> +  if ((path1[1] == '/') != (path2[1] == '/'))

All the tests against a literal '/' should be replaced with IS_SLASH,
to be portable to MS-Windows.

> +  while (*path1 && *path2)
> +    {
> +      if (*path1 != *path2)

This comparison should be case-insensitive for MS-Windows.

> +/* Either output STR to stdout or
> +   if *PBUF is not NULL then append STR to *PBUF
> +   and update *PBUF to point to the end of the buffer
> +   and adjust *PLEN to reflect the remaining space.

The punctuation here could use some improvement.

Also, I suggest to name PBUF differently to reflect the fact that it
is a pointer to the end of the buffer, not to its beginning.

> +   Return TRUE on failure.  */

That is a strange semantics, IMO.  Why not return an int instead of a
bool, if you want an error indication that you can conveniently
accumulate with a bitwise OR?

> +  else
> +    {
> +      fputs (str, stdout);
> +    }

Style: these braces are unnecessary, I think.

> +/* Output the relative representation if possible.
> +   If BUF is non NULL, write to that buffer rather than to stdout.  */

This doesn't document most of the arguments and the return value.

Also, the "can_" part hints that the argument file names are expected
to be canonicalized, but the commentary doesn't say so.

> +  /* Skip the prefix common to --relative-to and path.  */

The references to --relative-to should be replaced (here and
elsewhere), as they no longer make sense in the gnulib context.

> +  /* Skip over extraneous '/'.  */
> +  if (*relto_suffix == '/')
> +    relto_suffix++;
> +  if (*fname_suffix == '/')
> +    fname_suffix++;

Why do you skip only over a single slash?  Can't there be an
arbitrarily long sequence of redundant slashes?

> +  if (buf_err)
> +    error (0, ENAMETOOLONG, "%s", _("generating relative path"));

This looks like some inside knowledge of what happens inside
buffer_or_output.  Why not set errno inside that function instead?
And I think the commentary to buffer_or_output should mention this.

> +/* Return FROM represented as relative to the dir of TARGET.
> +   The result is malloced.  */

This commentary doesn't say that the result can be NULL.

> +
> +char *
> +convert_abs_rel (const char *from, const char *target)
> +{
> +  char *realtarget = canonicalize_filename_mode (target, CAN_MISSING);
> +  char *realfrom = canonicalize_filename_mode (from, CAN_MISSING);

AFAICT, canonicalize_filename_mode can return NULL, but the rest of
the code doesn't cope with that.  In particular, ...

> +  /* Write to a PATH_MAX buffer.  */
> +  char *relative_from = xmalloc (PATH_MAX);
> +
> +  /* Get dirname to generate paths relative to.  */
> +  realtarget[dir_len (realtarget)] = '\0';

... wouldn't the last line segfault if realtarget is NULL?

HTH



reply via email to

[Prev in Thread] Current Thread [Next in Thread]