delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2006/12/01/06:02:38

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Trace-PostClient-IP: 68.147.232.190
From: Brian Inglis <Brian DOT Inglis AT SystematicSW DOT Invalid>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: fnmatch("\\\\", "\\", 0) == 1 ???
Organization: Systematic Software
Message-ID: <guvvm2pvua65hjcv3tkfls4n919qu3j9fp@4ax.com>
References: <iKydndAovO98z_DYnZ2dnUVZ_sadnZ2d AT comcast DOT com> <LO6dnbePOLnKzvDYnZ2dnUVZ_sGdnZ2d AT comcast DOT com> <456dad03$0$486$cc7c7865 AT news DOT luth DOT se> <200611291634 DOT kATGYcbw010800 AT envy DOT delorie DOT com> <n6qsm2l2pk3svjtu7aqu68mmhdmvldprk5 AT 4ax DOT com> <Sb6dnSX2_Plh5_PYnZ2dnUVZ_rSdnZ2d AT comcast DOT com>
X-Newsreader: Forte Agent 1.93/32.576 English (American)
MIME-Version: 1.0
Lines: 95
Date: Fri, 01 Dec 2006 10:49:42 GMT
NNTP-Posting-Host: 64.59.135.176
X-Complaints-To: abuse AT shaw DOT ca
X-Trace: pd7urf2no 1164970182 64.59.135.176 (Fri, 01 Dec 2006 03:49:42 MST)
NNTP-Posting-Date: Fri, 01 Dec 2006 03:49:42 MST
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

On Wed, 29 Nov 2006 22:31:24 -0800 in comp.os.msdos.djgpp, "Alexei A.
Frounze" <alexfru AT chat DOT ru> wrote:

>Brian Inglis wrote:
>> fOn Wed, 29 Nov 2006 11:34:38 -0500 in comp.os.msdos.djgpp, DJ Delorie
>> <dj AT delorie DOT com> wrote:
>>
>>>
>>>> This function indicates if STRING matches the PATTERN. ..."
>>>>
>>>> So DJGPP says that "\" doesn't match "\\" while Linux says it does.
>>>>
>>>> Well, I say DJGPP is right as the pattern says there should be two
>>>> backslashes and you only provide one.
>>>
>>> Except that PATTERN is a regex influenced by FNM_NOESCAPE and
>>> FNM_PATHNAME, and STRING isn't.  So a pattern of "\\" is a single
>>> escaped backslash, whereas a string of "\" is a single backslash.
>>> They should match.
>>
>>    switch ((c = *pattern++))
>>    {
>> ...
>> ...
>> ...
>>    case '\\':
>> /*+++ pattern already post-incremented to point to next char */
>>      if (!(flags & FNM_NOESCAPE) && pattern[1] && strchr("*?[\\",
>> pattern[1]))
>> /*+++ should be:
>>      if (!(flags & FNM_NOESCAPE) && strchr("*?[\\", *pattern))
>> *+++ as end of input pattern will match end char in escapes string */
>>      {
>> /*+++ end of input pattern might be clearer with ! or == '\0' */
>>        if ((c = *pattern++) == 0)
>>        {
>>          c = '\\';
>>          --pattern;
>>        }
>>        if (c != *string++)
>>          return FNM_NOMATCH;
>>        break;
>>      }
>
>I don't think the above is enough. There's another problem. With the above 
>code you'd never see (c = *pattern++) == 0. My bet is that the intent was to 
>treat the slash in the last character of pattern as an ordinary character. 
AFAICS it does: strchr matches the nul pattern terminator with the nul
escapes constant terminator and returns a pointer to that character,
so the result is non-zero/true, as noted in the third +++ line. 
If "&& *pattern &&" was included, and a nul pattern terminator was
encountered, that if statement would be false and fallthrough to the
following default case, which is clearly not intended by the
subsequent test for the nul pattern terminator, which fixes things up
to treat a terminal \ as an ordinary character. 

>That would explain the {c = '\\'; --pattern;} thing along with the 
>fallthrough behavior. 

The break ensures that the fallthrough default case is skipped if an
escape is valid and there is a match, otherwise the previous return
happens. 

>But the code is broken in this place. Dunno if it was 
>tested against the single unix spec or just a little bit to see that it 
>seems to work (in some basic cases).

Handling of non-special escape characters here is punted to the
fallthrough default case and treated the same as FNM_NOESCAPE! 
Not sure if that is intentional or just inadequate. 
If non-special escape characters should be treated as a literal
character, the strchr() should be eliminated and only the nul
terminator handled specially as it is. 
The resulting code would look like:

    case '\\':				/* escape or directory	*/
      if (!(flags & FNM_NOESCAPE))	/* if escapes allowed	*/
      {
        if ((c = *pattern++) == '\0')	/* if next char end	*/
        {
          c = '\\';			/* trailing \ stays put	*/
          --pattern;			/* backup ptr to end	*/
        }

        if (c != *string++)		/* mismatch		*/
          return FNM_NOMATCH;		/*	quit		*/

        break;				/* done			*/
      }

-- 
Thanks. Take care, Brian Inglis 	Calgary, Alberta, Canada

Brian DOT Inglis AT CSi DOT com 	(Brian[dot]Inglis{at}SystematicSW[dot]ab[dot]ca)
    fake address		use address above to reply

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019