Edit

kc3-lang/gnulib/lib/strverscmp.c

Branch :

  • Show log

    Commit

  • Author : Paul Eggert
    Date : 2006-09-13 22:38:14
    Hash : 0632e115
    Message : * _fpending.c: Include <config.h> unconditionally, since we no longer worry about uses that don't define HAVE_CONFIG_H. * acl.c, alloca.c, argmatch.c, atexit.c, backupfile.c: * basename.c, c-stack.c, c-strtod.c, calloc.c, canon-host.c: * canonicalize.c, chdir-long.c, chdir-safer.c, chown.c: * cloexec.c, close-stream.c, closeout.c, creat-safer.c: * cycle-check.c, diacrit.c, dirchownmod.c, dirfd.c, dirname.c: * dup-safer.c, dup2.c, error.c, euidaccess.c, exclude.c: * exitfail.c, fchmodat.c, fchown-stub.c, fd-safer.c: * file-type.c, fileblocks.c, filemode.c, filenamecat.c: * fnmatch.c, fopen-safer.c, fprintftime.c, free.c, fsusage.c: * ftruncate.c, fts-cycle.c, fts.c, full-write.c, gai_strerror.c: * getcwd.c, getdate.y, getdomainname.c, getgroups.c: * gethostname.c, gethrxtime.c, getloadavg.c, getlogin_r.c: * getndelim2.c, getnline.c, getopt.c, getopt1.c, getpass.c: * gettime.c, gettimeofday.c, getugroups.c, getusershell.c: * glob.c, group-member.c, hard-locale.c, hash-pjw.c, hash.c: * human.c, idcache.c, inet_ntop.c, inet_pton.c, inttostr.c: * isdir.c, lchown.c, linebuffer.c, long-options.c, lstat.c: * malloc.c, md5.c, memcasecmp.c, memchr.c, memcmp.c, memcoll.c: * memcpy.c, memmove.c, memrchr.c, mkancesdirs.c, mkdir-p.c: * mkdir.c, mkdirat.c, mkstemp-safer.c, mkstemp.c, modechange.c: * mountlist.c, nanosleep.c, obstack.c, open-safer.c: * openat-die.c, openat.c, pagealign_alloc.c, physmem.c: * pipe-safer.c, posixtm.c, posixver.c, putenv.c, quote.c: * quotearg.c, raise.c, readtokens.c, readtokens0.c, readutmp.c: * realloc.c, regex.c, rename.c, rmdir.c, rpmatch.c, safe-read.c: * same.c, save-cwd.c, savedir.c, setenv.c, settime.c, sha1.c: * sig2str.c, snprintf.c, strdup.c, strerror.c, strftime.c: * stripslash.c, strndup.c, strnlen.c, strpbrk.c, strtod.c: * strtoimax.c, strtol.c, strverscmp.c, tempname.c, time_r.c: * timegm.c, tmpfile-safer.c, unlinkdir.c, userspec.c, utime.c: * utimecmp.c, utimens.c, version-etc-fsf.c, version-etc.c: * xalloc-die.c, xgetcwd.c, xgethostname.c, xmalloc.c: * xmemcoll.c, xnanosleep.c, xreadlink.c, xstrtod.c: * xstrtoimax.c, xstrtol.c, xstrtoumax.c, yesno.c: Likewise.

  • lib/strverscmp.c
  • /* Compare strings while treating digits characters numerically.
       Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc.
       This file is part of the GNU C Library.
       Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
    
       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2, or (at your option)
       any later version.
    
       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.
    
       You should have received a copy of the GNU General Public License along
       with this program; if not, write to the Free Software Foundation,
       Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
    
    #if !_LIBC
    # include <config.h>
    #endif
    
    #include <string.h>
    #include <ctype.h>
    
    /* states: S_N: normal, S_I: comparing integral part, S_F: comparing
               fractional parts, S_Z: idem but with leading Zeroes only */
    #define S_N    0x0
    #define S_I    0x4
    #define S_F    0x8
    #define S_Z    0xC
    
    /* result_type: CMP: return diff; LEN: compare using len_diff/diff */
    #define CMP    2
    #define LEN    3
    
    
    /* ISDIGIT differs from isdigit, as follows:
       - Its arg may be any int or unsigned int; it need not be an unsigned char
         or EOF.
       - It's typically faster.
       POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
       isdigit unless it's important to use the locale's definition
       of `digit' even when the host does not conform to POSIX.  */
    #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
    
    #undef __strverscmp
    #undef strverscmp
    
    #ifndef weak_alias
    # define __strverscmp strverscmp
    #endif
    
    /* Compare S1 and S2 as strings holding indices/version numbers,
       returning less than, equal to or greater than zero if S1 is less than,
       equal to or greater than S2 (for more info, see the texinfo doc).
    */
    
    int
    __strverscmp (const char *s1, const char *s2)
    {
      const unsigned char *p1 = (const unsigned char *) s1;
      const unsigned char *p2 = (const unsigned char *) s2;
      unsigned char c1, c2;
      int state;
      int diff;
    
      /* Symbol(s)    0       [1-9]   others  (padding)
         Transition   (10) 0  (01) d  (00) x  (11) -   */
      static const unsigned int next_state[] =
      {
          /* state    x    d    0    - */
          /* S_N */  S_N, S_I, S_Z, S_N,
          /* S_I */  S_N, S_I, S_I, S_I,
          /* S_F */  S_N, S_F, S_F, S_F,
          /* S_Z */  S_N, S_F, S_Z, S_Z
      };
    
      static const int result_type[] =
      {
          /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
                     0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
    
          /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
                     CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
          /* S_I */  CMP, -1,  -1,  CMP,  1,  LEN, LEN, CMP,
                      1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
          /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
                     CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
          /* S_Z */  CMP,  1,   1,  CMP, -1,  CMP, CMP, CMP,
                     -1,  CMP, CMP, CMP
      };
    
      if (p1 == p2)
        return 0;
    
      c1 = *p1++;
      c2 = *p2++;
      /* Hint: '0' is a digit too.  */
      state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
    
      while ((diff = c1 - c2) == 0 && c1 != '\0')
        {
          state = next_state[state];
          c1 = *p1++;
          c2 = *p2++;
          state |= (c1 == '0') + (ISDIGIT (c1) != 0);
        }
    
      state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
    
      switch (state)
        {
        case CMP:
          return diff;
    
        case LEN:
          while (ISDIGIT (*p1++))
    	if (!ISDIGIT (*p2++))
    	  return 1;
    
          return ISDIGIT (*p2) ? -1 : diff;
    
        default:
          return state;
        }
    }
    #ifdef weak_alias
    weak_alias (__strverscmp, strverscmp)
    #endif