LCOV - code coverage report
Current view: top level - common - stringhelp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 450 564 79.8 %
Date: 2016-11-29 15:00:56 Functions: 42 48 87.5 %

          Line data    Source code
       1             : /* stringhelp.c -  standard string helper functions
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
       3             :  *               2008, 2009, 2010  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2014 Werner Koch
       5             :  * Copyright (C) 2015  g10 Code GmbH
       6             :  *
       7             :  * This file is part of GnuPG.
       8             :  *
       9             :  * GnuPG is free software; you can redistribute it and/or modify it
      10             :  * under the terms of either
      11             :  *
      12             :  *   - the GNU Lesser General Public License as published by the Free
      13             :  *     Software Foundation; either version 3 of the License, or (at
      14             :  *     your option) any later version.
      15             :  *
      16             :  * or
      17             :  *
      18             :  *   - the GNU General Public License as published by the Free
      19             :  *     Software Foundation; either version 2 of the License, or (at
      20             :  *     your option) any later version.
      21             :  *
      22             :  * or both in parallel, as here.
      23             :  *
      24             :  * GnuPG is distributed in the hope that it will be useful, but
      25             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      26             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      27             :  * General Public License for more details.
      28             :  *
      29             :  * You should have received a copies of the GNU General Public License
      30             :  * and the GNU Lesser General Public License along with this program;
      31             :  * if not, see <https://www.gnu.org/licenses/>.
      32             :  */
      33             : 
      34             : #include <config.h>
      35             : #include <stdlib.h>
      36             : #include <string.h>
      37             : #include <stdarg.h>
      38             : #include <ctype.h>
      39             : #include <errno.h>
      40             : #ifdef HAVE_PWD_H
      41             : # include <pwd.h>
      42             : #endif
      43             : #include <unistd.h>
      44             : #include <sys/types.h>
      45             : #ifdef HAVE_W32_SYSTEM
      46             : # ifdef HAVE_WINSOCK2_H
      47             : #  include <winsock2.h>
      48             : # endif
      49             : # include <windows.h>
      50             : #endif
      51             : #include <assert.h>
      52             : #include <limits.h>
      53             : 
      54             : #include "util.h"
      55             : #include "common-defs.h"
      56             : #include "utf8conv.h"
      57             : #include "sysutils.h"
      58             : #include "stringhelp.h"
      59             : 
      60             : #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
      61             : 
      62             : 
      63             : /* Sometimes we want to avoid mixing slashes and backslashes on W32
      64             :    and prefer backslashes.  There is usual no problem with mixing
      65             :    them, however a very few W32 API calls can't grok plain slashes.
      66             :    Printing filenames with mixed slashes also looks a bit strange.
      67             :    This function has no effext on POSIX. */
      68             : static inline char *
      69       17166 : change_slashes (char *name)
      70             : {
      71             : #ifdef HAVE_DOSISH_SYSTEM
      72             :   char *p;
      73             : 
      74             :   if (strchr (name, '\\'))
      75             :     {
      76             :       for (p=name; *p; p++)
      77             :         if (*p == '/')
      78             :           *p = '\\';
      79             :     }
      80             : #endif /*HAVE_DOSISH_SYSTEM*/
      81       17166 :   return name;
      82             : }
      83             : 
      84             : 
      85             : /*
      86             :  * Check whether STRING starts with KEYWORD.  The keyword is
      87             :  * delimited by end of string, a space or a tab.  Returns NULL if not
      88             :  * found or a pointer into STRING to the next non-space character
      89             :  * after the KEYWORD (which may be end of string).
      90             :  */
      91             : char *
      92        1894 : has_leading_keyword (const char *string, const char *keyword)
      93             : {
      94        1894 :   size_t n = strlen (keyword);
      95             : 
      96        1894 :   if (!strncmp (string, keyword, n)
      97         783 :       && (!string[n] || string[n] == ' ' || string[n] == '\t'))
      98             :     {
      99         783 :       string += n;
     100        2049 :       while (*string == ' ' || *string == '\t')
     101         483 :         string++;
     102         783 :       return (char*)string;
     103             :     }
     104        1111 :   return NULL;
     105             : }
     106             : 
     107             : 
     108             : /*
     109             :  * Look for the substring SUB in buffer and return a pointer to that
     110             :  * substring in BUFFER or NULL if not found.
     111             :  * Comparison is case-insensitive.
     112             :  */
     113             : const char *
     114          44 : memistr (const void *buffer, size_t buflen, const char *sub)
     115             : {
     116          44 :   const unsigned char *buf = buffer;
     117          44 :   const unsigned char *t = (const unsigned char *)buffer;
     118          44 :   const unsigned char *s = (const unsigned char *)sub;
     119          44 :   size_t n = buflen;
     120             : 
     121         232 :   for ( ; n ; t++, n-- )
     122             :     {
     123         214 :       if ( toupper (*t) == toupper (*s) )
     124             :         {
     125         234 :           for ( buf=t++, buflen = n--, s++;
     126         310 :                 n && toupper (*t) == toupper (*s); t++, s++, n-- )
     127             :             ;
     128          46 :           if (!*s)
     129          26 :             return (const char*)buf;
     130          20 :           t = buf;
     131          20 :           s = (const unsigned char *)sub ;
     132          20 :           n = buflen;
     133             :         }
     134             :     }
     135          18 :   return NULL;
     136             : }
     137             : 
     138             : const char *
     139           1 : ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
     140             : {
     141           1 :   const unsigned char *buf = buffer;
     142           1 :   const unsigned char *t = (const unsigned char *)buf;
     143           1 :   const unsigned char *s = (const unsigned char *)sub;
     144           1 :   size_t n = buflen;
     145             : 
     146           1 :   for ( ; n ; t++, n-- )
     147             :     {
     148           1 :       if (ascii_toupper (*t) == ascii_toupper (*s) )
     149             :         {
     150           6 :           for ( buf=t++, buflen = n--, s++;
     151           9 :                 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
     152             :             ;
     153           1 :           if (!*s)
     154           1 :             return (const char*)buf;
     155           0 :           t = (const unsigned char *)buf;
     156           0 :           s = (const unsigned char *)sub ;
     157           0 :           n = buflen;
     158             :         }
     159             :     }
     160           0 :   return NULL;
     161             : }
     162             : 
     163             : /* This function is similar to strncpy().  However it won't copy more
     164             :    than N - 1 characters and makes sure that a '\0' is appended. With
     165             :    N given as 0, nothing will happen.  With DEST given as NULL, memory
     166             :    will be allocated using xmalloc (i.e. if it runs out of core
     167             :    the function terminates).  Returns DES or a pointer to the
     168             :    allocated memory.
     169             :  */
     170             : char *
     171         383 : mem2str( char *dest , const void *src , size_t n )
     172             : {
     173             :     char *d;
     174             :     const char *s;
     175             : 
     176         383 :     if( n ) {
     177         383 :         if( !dest )
     178           0 :             dest = xmalloc( n ) ;
     179         383 :         d = dest;
     180         383 :         s = src ;
     181        5887 :         for(n--; n && *s; n-- )
     182        5504 :             *d++ = *s++;
     183         383 :         *d = '\0' ;
     184             :     }
     185             : 
     186         383 :     return dest ;
     187             : }
     188             : 
     189             : 
     190             : /****************
     191             :  * remove leading and trailing white spaces
     192             :  */
     193             : char *
     194        1371 : trim_spaces( char *str )
     195             : {
     196             :     char *string, *p, *mark;
     197             : 
     198        1371 :     string = str;
     199             :     /* find first non space character */
     200        1371 :     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
     201             :         ;
     202             :     /* move characters */
     203       86374 :     for( (mark = NULL); (*string = *p); string++, p++ )
     204       85003 :         if( isspace( *(byte*)p ) ) {
     205          62 :             if( !mark )
     206          58 :                 mark = string ;
     207             :         }
     208             :         else
     209       84941 :             mark = NULL ;
     210        1371 :     if( mark )
     211          56 :         *mark = '\0' ;  /* remove trailing spaces */
     212             : 
     213        1371 :     return str ;
     214             : }
     215             : 
     216             : /****************
     217             :  * remove trailing white spaces
     218             :  */
     219             : char *
     220           0 : trim_trailing_spaces( char *string )
     221             : {
     222             :     char *p, *mark;
     223             : 
     224           0 :     for( mark = NULL, p = string; *p; p++ ) {
     225           0 :         if( isspace( *(byte*)p ) ) {
     226           0 :             if( !mark )
     227           0 :                 mark = p;
     228             :         }
     229             :         else
     230           0 :             mark = NULL;
     231             :     }
     232           0 :     if( mark )
     233           0 :         *mark = '\0' ;
     234             : 
     235           0 :     return string ;
     236             : }
     237             : 
     238             : 
     239             : unsigned
     240        5502 : trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
     241             : {
     242             :     byte *p, *mark;
     243             :     unsigned n;
     244             : 
     245      224420 :     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
     246      218918 :         if( strchr(trimchars, *p ) ) {
     247       40792 :             if( !mark )
     248       34749 :                 mark = p;
     249             :         }
     250             :         else
     251      178126 :             mark = NULL;
     252             :     }
     253             : 
     254        5502 :     if( mark ) {
     255        5437 :         *mark = 0;
     256        5437 :         return mark - line;
     257             :     }
     258          65 :     return len;
     259             : }
     260             : 
     261             : /****************
     262             :  * remove trailing white spaces and return the length of the buffer
     263             :  */
     264             : unsigned
     265          30 : trim_trailing_ws( byte *line, unsigned len )
     266             : {
     267          30 :     return trim_trailing_chars( line, len, " \t\r\n" );
     268             : }
     269             : 
     270             : size_t
     271         380 : length_sans_trailing_chars (const unsigned char *line, size_t len,
     272             :                             const char *trimchars )
     273             : {
     274             :   const unsigned char *p, *mark;
     275             :   size_t n;
     276             : 
     277        4626 :   for( mark=NULL, p=line, n=0; n < len; n++, p++ )
     278             :     {
     279        4246 :       if (strchr (trimchars, *p ))
     280             :         {
     281         797 :           if( !mark )
     282         797 :             mark = p;
     283             :         }
     284             :       else
     285        3449 :         mark = NULL;
     286             :     }
     287             : 
     288         380 :   if (mark)
     289         380 :     return mark - line;
     290           0 :   return len;
     291             : }
     292             : 
     293             : /*
     294             :  *  Return the length of line ignoring trailing white-space.
     295             :  */
     296             : size_t
     297         380 : length_sans_trailing_ws (const unsigned char *line, size_t len)
     298             : {
     299         380 :   return length_sans_trailing_chars (line, len, " \t\r\n");
     300             : }
     301             : 
     302             : 
     303             : 
     304             : /*
     305             :  * Extract from a given path the filename component.  This function
     306             :  * terminates the process on memory shortage.
     307             :  */
     308             : char *
     309         334 : make_basename(const char *filepath, const char *inputpath)
     310             : {
     311             : #ifdef __riscos__
     312             :     return riscos_make_basename(filepath, inputpath);
     313             : #else
     314             :     char *p;
     315             : 
     316             :     (void)inputpath; /* Only required for riscos.  */
     317             : 
     318         334 :     if ( !(p=strrchr(filepath, '/')) )
     319             : #ifdef HAVE_DOSISH_SYSTEM
     320             :         if ( !(p=strrchr(filepath, '\\')) )
     321             : #endif
     322             : #ifdef HAVE_DRIVE_LETTERS
     323             :             if ( !(p=strrchr(filepath, ':')) )
     324             : #endif
     325             :               {
     326         334 :                 return xstrdup(filepath);
     327             :               }
     328             : 
     329           0 :     return xstrdup(p+1);
     330             : #endif
     331             : }
     332             : 
     333             : 
     334             : 
     335             : /*
     336             :  * Extract from a given filename the path prepended to it.  If there
     337             :  * isn't a path prepended to the filename, a dot is returned ('.').
     338             :  * This function terminates the process on memory shortage.
     339             :  */
     340             : char *
     341          33 : make_dirname(const char *filepath)
     342             : {
     343             :     char *dirname;
     344             :     int  dirname_length;
     345             :     char *p;
     346             : 
     347          33 :     if ( !(p=strrchr(filepath, '/')) )
     348             : #ifdef HAVE_DOSISH_SYSTEM
     349             :         if ( !(p=strrchr(filepath, '\\')) )
     350             : #endif
     351             : #ifdef HAVE_DRIVE_LETTERS
     352             :             if ( !(p=strrchr(filepath, ':')) )
     353             : #endif
     354             :               {
     355           0 :                 return xstrdup(".");
     356             :               }
     357             : 
     358          33 :     dirname_length = p-filepath;
     359          33 :     dirname = xmalloc(dirname_length+1);
     360          33 :     strncpy(dirname, filepath, dirname_length);
     361          33 :     dirname[dirname_length] = 0;
     362             : 
     363          33 :     return dirname;
     364             : }
     365             : 
     366             : 
     367             : 
     368             : static char *
     369           0 : get_pwdir (int xmode, const char *name)
     370             : {
     371           0 :   char *result = NULL;
     372             : #ifdef HAVE_PWD_H
     373           0 :   struct passwd *pwd = NULL;
     374             : 
     375           0 :   if (name)
     376             :     {
     377             : #ifdef HAVE_GETPWNAM
     378             :       /* Fixme: We should use getpwnam_r if available.  */
     379           0 :       pwd = getpwnam (name);
     380             : #endif
     381             :     }
     382             :   else
     383             :     {
     384             : #ifdef HAVE_GETPWUID
     385             :       /* Fixme: We should use getpwuid_r if available.  */
     386           0 :       pwd = getpwuid (getuid());
     387             : #endif
     388             :     }
     389           0 :   if (pwd)
     390             :     {
     391           0 :       if (xmode)
     392           0 :         result = xstrdup (pwd->pw_dir);
     393             :       else
     394           0 :         result = xtrystrdup (pwd->pw_dir);
     395             :     }
     396             : #else /*!HAVE_PWD_H*/
     397             :   /* No support at all.  */
     398             :   (void)xmode;
     399             :   (void)name;
     400             : #endif /*HAVE_PWD_H*/
     401           0 :   return result;
     402             : }
     403             : 
     404             : 
     405             : /* xmode 0 := Return NULL on error
     406             :          1 := Terminate on error
     407             :          2 := Make sure that name is absolute; return NULL on error
     408             :          3 := Make sure that name is absolute; terminate on error
     409             :  */
     410             : static char *
     411       17168 : do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
     412             : {
     413             :   const char *argv[32];
     414             :   int argc;
     415             :   size_t n;
     416       17168 :   int skip = 1;
     417       17168 :   char *home_buffer = NULL;
     418             :   char *name, *home, *p;
     419             :   int want_abs;
     420             : 
     421       17168 :   want_abs = !!(xmode & 2);
     422       17168 :   xmode &= 1;
     423             : 
     424       17168 :   n = strlen (first_part) + 1;
     425       17168 :   argc = 0;
     426       48407 :   while ( (argv[argc] = va_arg (arg_ptr, const char *)) )
     427             :     {
     428       14073 :       n += strlen (argv[argc]) + 1;
     429       14073 :       if (argc >= DIM (argv)-1)
     430             :         {
     431           2 :           if (xmode)
     432           0 :             BUG ();
     433           2 :           gpg_err_set_errno (EINVAL);
     434           2 :           return NULL;
     435             :         }
     436       14071 :       argc++;
     437             :     }
     438       17166 :   n++;
     439             : 
     440       17166 :   home = NULL;
     441       17166 :   if (*first_part == '~')
     442             :     {
     443        1651 :       if (first_part[1] == '/' || !first_part[1])
     444             :         {
     445             :           /* This is the "~/" or "~" case.  */
     446        1651 :           home = getenv("HOME");
     447        1651 :           if (!home)
     448           0 :             home = home_buffer = get_pwdir (xmode, NULL);
     449        3302 :           if (home && *home)
     450        1651 :             n += strlen (home);
     451             :         }
     452             :       else
     453             :         {
     454             :           /* This is the "~username/" or "~username" case.  */
     455             :           char *user;
     456             : 
     457           0 :           if (xmode)
     458           0 :             user = xstrdup (first_part+1);
     459             :           else
     460             :             {
     461           0 :               user = xtrystrdup (first_part+1);
     462           0 :               if (!user)
     463           0 :                 return NULL;
     464             :             }
     465           0 :           p = strchr (user, '/');
     466           0 :           if (p)
     467           0 :             *p = 0;
     468           0 :           skip = 1 + strlen (user);
     469             : 
     470           0 :           home = home_buffer = get_pwdir (xmode, user);
     471           0 :           xfree (user);
     472           0 :           if (home)
     473           0 :             n += strlen (home);
     474             :           else
     475           0 :             skip = 1;
     476             :         }
     477             :     }
     478             : 
     479       17166 :   if (xmode)
     480       16416 :     name = xmalloc (n);
     481             :   else
     482             :     {
     483         750 :       name = xtrymalloc (n);
     484         750 :       if (!name)
     485             :         {
     486           0 :           xfree (home_buffer);
     487           0 :           return NULL;
     488             :         }
     489             :     }
     490             : 
     491       17166 :   if (home)
     492        1651 :     p = stpcpy (stpcpy (name, home), first_part + skip);
     493             :   else
     494       15515 :     p = stpcpy (name, first_part);
     495             : 
     496       17166 :   xfree (home_buffer);
     497       31175 :   for (argc=0; argv[argc]; argc++)
     498             :     {
     499             :       /* Avoid a leading double slash if the first part was "/".  */
     500       14009 :       if (!argc && name[0] == '/' && !name[1])
     501           0 :         p = stpcpy (p, argv[argc]);
     502             :       else
     503       14009 :         p = stpcpy (stpcpy (p, "/"), argv[argc]);
     504             :     }
     505             : 
     506       17166 :   if (want_abs)
     507             :     {
     508             : #ifdef HAVE_DRIVE_LETTERS
     509             :       p = strchr (name, ':');
     510             :       if (p)
     511             :         p++;
     512             :       else
     513             :         p = name;
     514             : #else
     515        4957 :       p = name;
     516             : #endif
     517        4957 :       if (*p != '/'
     518             : #ifdef HAVE_DRIVE_LETTERS
     519             :           && *p != '\\'
     520             : #endif
     521             :           )
     522             :         {
     523           3 :           home = gnupg_getcwd ();
     524           3 :           if (!home)
     525             :             {
     526           0 :               if (xmode)
     527             :                 {
     528           0 :                   fprintf (stderr, "\nfatal: getcwd failed: %s\n",
     529           0 :                            strerror (errno));
     530           0 :                   exit(2);
     531             :                 }
     532           0 :               xfree (name);
     533           0 :               return NULL;
     534             :             }
     535           3 :           n = strlen (home) + 1 + strlen (name) + 1;
     536           3 :           if (xmode)
     537           0 :             home_buffer = xmalloc (n);
     538             :           else
     539             :             {
     540           3 :               home_buffer = xtrymalloc (n);
     541           3 :               if (!home_buffer)
     542             :                 {
     543           0 :                   xfree (home);
     544           0 :                   xfree (name);
     545           0 :                   return NULL;
     546             :                 }
     547             :             }
     548           3 :           if (p == name)
     549           3 :             p = home_buffer;
     550             :           else /* Windows case.  */
     551             :             {
     552           0 :               memcpy (home_buffer, p, p - name + 1);
     553           0 :               p = home_buffer + (p - name + 1);
     554             :             }
     555             : 
     556             :           /* Avoid a leading double slash if the cwd is "/".  */
     557           3 :           if (home[0] == '/' && !home[1])
     558           0 :             strcpy (stpcpy (p, "/"), name);
     559             :           else
     560           3 :             strcpy (stpcpy (stpcpy (p, home), "/"), name);
     561             : 
     562           3 :           xfree (home);
     563           3 :           xfree (name);
     564           3 :           name = home_buffer;
     565             :           /* Let's do a simple compression to catch the most common
     566             :              case of using "." for gpg's --homedir option.  */
     567           3 :           n = strlen (name);
     568           3 :           if (n > 2 && name[n-2] == '/' && name[n-1] == '.')
     569           1 :             name[n-2] = 0;
     570             :         }
     571             :     }
     572       17166 :   return change_slashes (name);
     573             : }
     574             : 
     575             : /* Construct a filename from the NULL terminated list of parts.  Tilde
     576             :    expansion is done for the first argument.  This function terminates
     577             :    the process on memory shortage. */
     578             : char *
     579       11567 : make_filename (const char *first_part, ... )
     580             : {
     581             :   va_list arg_ptr;
     582             :   char *result;
     583             : 
     584       11567 :   va_start (arg_ptr, first_part);
     585       11567 :   result = do_make_filename (1, first_part, arg_ptr);
     586       11567 :   va_end (arg_ptr);
     587       11567 :   return result;
     588             : }
     589             : 
     590             : /* Construct a filename from the NULL terminated list of parts.  Tilde
     591             :    expansion is done for the first argument.  This function may return
     592             :    NULL on error. */
     593             : char *
     594         644 : make_filename_try (const char *first_part, ... )
     595             : {
     596             :   va_list arg_ptr;
     597             :   char *result;
     598             : 
     599         644 :   va_start (arg_ptr, first_part);
     600         644 :   result = do_make_filename (0, first_part, arg_ptr);
     601         644 :   va_end (arg_ptr);
     602         644 :   return result;
     603             : }
     604             : 
     605             : /* Construct an absolute filename from the NULL terminated list of
     606             :    parts.  Tilde expansion is done for the first argument.  This
     607             :    function terminates the process on memory shortage. */
     608             : char *
     609        4849 : make_absfilename (const char *first_part, ... )
     610             : {
     611             :   va_list arg_ptr;
     612             :   char *result;
     613             : 
     614        4849 :   va_start (arg_ptr, first_part);
     615        4849 :   result = do_make_filename (3, first_part, arg_ptr);
     616        4849 :   va_end (arg_ptr);
     617        4849 :   return result;
     618             : }
     619             : 
     620             : /* Construct an absolute filename from the NULL terminated list of
     621             :    parts.  Tilde expansion is done for the first argument.  This
     622             :    function may return NULL on error. */
     623             : char *
     624         108 : make_absfilename_try (const char *first_part, ... )
     625             : {
     626             :   va_list arg_ptr;
     627             :   char *result;
     628             : 
     629         108 :   va_start (arg_ptr, first_part);
     630         108 :   result = do_make_filename (2, first_part, arg_ptr);
     631         108 :   va_end (arg_ptr);
     632         108 :   return result;
     633             : }
     634             : 
     635             : 
     636             : 
     637             : /* Compare whether the filenames are identical.  This is a
     638             :    special version of strcmp() taking the semantics of filenames in
     639             :    account.  Note that this function works only on the supplied names
     640             :    without considering any context like the current directory.  See
     641             :    also same_file_p(). */
     642             : int
     643        1607 : compare_filenames (const char *a, const char *b)
     644             : {
     645             : #ifdef HAVE_DOSISH_SYSTEM
     646             :   for ( ; *a && *b; a++, b++ )
     647             :     {
     648             :       if (*a != *b
     649             :           && (toupper (*(const unsigned char*)a)
     650             :               != toupper (*(const unsigned char*)b) )
     651             :           && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
     652             :         break;
     653             :     }
     654             :   if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
     655             :     return 0;
     656             :   else
     657             :     return (toupper (*(const unsigned char*)a)
     658             :             - toupper (*(const unsigned char*)b));
     659             : #else
     660        1607 :     return strcmp(a,b);
     661             : #endif
     662             : }
     663             : 
     664             : 
     665             : /* Convert a base-10 number in STRING into a 64 bit unsigned int
     666             :  * value.  Leading white spaces are skipped but no error checking is
     667             :  * done.  Thus it is similar to atoi(). */
     668             : uint64_t
     669           0 : string_to_u64 (const char *string)
     670             : {
     671           0 :   uint64_t val = 0;
     672             : 
     673           0 :   while (spacep (string))
     674           0 :     string++;
     675           0 :   for (; digitp (string); string++)
     676             :     {
     677           0 :       val *= 10;
     678           0 :       val += *string - '0';
     679             :     }
     680           0 :   return val;
     681             : }
     682             : 
     683             : 
     684             : /* Convert 2 hex characters at S to a byte value.  Return this value
     685             :    or -1 if there is an error. */
     686             : int
     687        3880 : hextobyte (const char *s)
     688             : {
     689             :   int c;
     690             : 
     691        3880 :   if ( *s >= '0' && *s <= '9' )
     692        2466 :     c = 16 * (*s - '0');
     693        1414 :   else if ( *s >= 'A' && *s <= 'F' )
     694        1414 :     c = 16 * (10 + *s - 'A');
     695           0 :   else if ( *s >= 'a' && *s <= 'f' )
     696           0 :     c = 16 * (10 + *s - 'a');
     697             :   else
     698           0 :     return -1;
     699        3880 :   s++;
     700        3880 :   if ( *s >= '0' && *s <= '9' )
     701        2415 :     c += *s - '0';
     702        1465 :   else if ( *s >= 'A' && *s <= 'F' )
     703        1465 :     c += 10 + *s - 'A';
     704           0 :   else if ( *s >= 'a' && *s <= 'f' )
     705           0 :     c += 10 + *s - 'a';
     706             :   else
     707           0 :     return -1;
     708        3880 :   return c;
     709             : }
     710             : 
     711             : /* Given a string containing an UTF-8 encoded text, return the number
     712             :    of characters in this string.  It differs from strlen in that it
     713             :    only counts complete UTF-8 characters.  SIZE is the maximum length
     714             :    of the string in bytes.  If SIZE is -1, then a NUL character is
     715             :    taken to be the end of the string.  Note, that this function does
     716             :    not take combined characters into account.  */
     717             : size_t
     718        1278 : utf8_charcount (const char *s, int len)
     719             : {
     720             :   size_t n;
     721             : 
     722        1278 :   if (len == 0)
     723          70 :     return 0;
     724             : 
     725       40919 :   for (n=0; *s; s++)
     726             :     {
     727       40914 :       if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
     728       40914 :         n++;
     729             : 
     730       40914 :       if (len != -1)
     731             :         {
     732       40875 :           len --;
     733       40875 :           if (len == 0)
     734        1203 :             break;
     735             :         }
     736             :     }
     737             : 
     738        1208 :   return n;
     739             : }
     740             : 
     741             : 
     742             : /****************************************************
     743             :  **********  W32 specific functions  ****************
     744             :  ****************************************************/
     745             : 
     746             : #ifdef HAVE_W32_SYSTEM
     747             : const char *
     748             : w32_strerror (int ec)
     749             : {
     750             :   static char strerr[256];
     751             : 
     752             :   if (ec == -1)
     753             :     ec = (int)GetLastError ();
     754             : #ifdef HAVE_W32CE_SYSTEM
     755             :   /* There is only a wchar_t FormatMessage.  It does not make much
     756             :      sense to play the conversion game; we print only the code.  */
     757             :   snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ());
     758             : #else
     759             :   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
     760             :                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
     761             :                  strerr, DIM (strerr)-1, NULL);
     762             : #endif
     763             :   return strerr;
     764             : }
     765             : #endif /*HAVE_W32_SYSTEM*/
     766             : 
     767             : 
     768             : /****************************************************
     769             :  ******** Locale insensitive ctype functions ********
     770             :  ****************************************************/
     771             : /* FIXME: replace them by a table lookup and macros */
     772             : int
     773           0 : ascii_isupper (int c)
     774             : {
     775           0 :     return c >= 'A' && c <= 'Z';
     776             : }
     777             : 
     778             : int
     779           0 : ascii_islower (int c)
     780             : {
     781           0 :     return c >= 'a' && c <= 'z';
     782             : }
     783             : 
     784             : int
     785      825552 : ascii_toupper (int c)
     786             : {
     787      825552 :     if (c >= 'a' && c <= 'z')
     788      624011 :         c &= ~0x20;
     789      825552 :     return c;
     790             : }
     791             : 
     792             : int
     793        3245 : ascii_tolower (int c)
     794             : {
     795        3245 :     if (c >= 'A' && c <= 'Z')
     796         372 :         c |= 0x20;
     797        3245 :     return c;
     798             : }
     799             : 
     800             : /* Lowercase all ASCII characters in S.  */
     801             : char *
     802         627 : ascii_strlwr (char *s)
     803             : {
     804         627 :   char *p = s;
     805             : 
     806        9403 :   for (p=s; *p; p++ )
     807        8776 :     if (isascii (*p) && *p >= 'A' && *p <= 'Z')
     808         203 :       *p |= 0x20;
     809             : 
     810         627 :   return s;
     811             : }
     812             : 
     813             : int
     814        8034 : ascii_strcasecmp( const char *a, const char *b )
     815             : {
     816        8034 :     if (a == b)
     817           0 :         return 0;
     818             : 
     819       35367 :     for (; *a && *b; a++, b++) {
     820       33398 :         if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
     821        6065 :             break;
     822             :     }
     823        8034 :     return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
     824             : }
     825             : 
     826             : int
     827         151 : ascii_strncasecmp (const char *a, const char *b, size_t n)
     828             : {
     829         151 :   const unsigned char *p1 = (const unsigned char *)a;
     830         151 :   const unsigned char *p2 = (const unsigned char *)b;
     831             :   unsigned char c1, c2;
     832             : 
     833         151 :   if (p1 == p2 || !n )
     834           0 :     return 0;
     835             : 
     836             :   do
     837             :     {
     838        1618 :       c1 = ascii_tolower (*p1);
     839        1618 :       c2 = ascii_tolower (*p2);
     840             : 
     841        1618 :       if ( !--n || c1 == '\0')
     842             :         break;
     843             : 
     844        1582 :       ++p1;
     845        1582 :       ++p2;
     846             :     }
     847        1582 :   while (c1 == c2);
     848             : 
     849         151 :   return c1 - c2;
     850             : }
     851             : 
     852             : 
     853             : int
     854      198254 : ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
     855             : {
     856      198254 :   const char *a = a_arg;
     857      198254 :   const char *b = b_arg;
     858             : 
     859      198254 :   if (a == b)
     860           0 :     return 0;
     861      217241 :   for ( ; n; n--, a++, b++ )
     862             :     {
     863      217024 :       if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
     864      198037 :         return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
     865             :     }
     866         217 :   return 0;
     867             : }
     868             : 
     869             : int
     870           0 : ascii_strcmp( const char *a, const char *b )
     871             : {
     872           0 :     if (a == b)
     873           0 :         return 0;
     874             : 
     875           0 :     for (; *a && *b; a++, b++) {
     876           0 :         if (*a != *b )
     877           0 :             break;
     878             :     }
     879           0 :     return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
     880             : }
     881             : 
     882             : 
     883             : void *
     884        8577 : ascii_memcasemem (const void *haystack, size_t nhaystack,
     885             :                   const void *needle, size_t nneedle)
     886             : {
     887             : 
     888        8577 :   if (!nneedle)
     889           0 :     return (void*)haystack; /* finding an empty needle is really easy */
     890        8577 :   if (nneedle <= nhaystack)
     891             :     {
     892        8225 :       const char *a = haystack;
     893        8225 :       const char *b = a + nhaystack - nneedle;
     894             : 
     895      204544 :       for (; a <= b; a++)
     896             :         {
     897      196536 :           if ( !ascii_memcasecmp (a, needle, nneedle) )
     898         217 :             return (void *)a;
     899             :         }
     900             :     }
     901        8360 :   return NULL;
     902             : }
     903             : 
     904             : /*********************************************
     905             :  ********** missing string functions *********
     906             :  *********************************************/
     907             : 
     908             : #ifndef HAVE_STPCPY
     909             : char *
     910             : stpcpy(char *a,const char *b)
     911             : {
     912             :     while( *b )
     913             :         *a++ = *b++;
     914             :     *a = 0;
     915             : 
     916             :     return (char*)a;
     917             : }
     918             : #endif
     919             : 
     920             : #ifndef HAVE_STRPBRK
     921             : /* Find the first occurrence in S of any character in ACCEPT.
     922             :    Code taken from glibc-2.6/string/strpbrk.c (LGPLv2.1+) and modified. */
     923             : char *
     924             : strpbrk (const char *s, const char *accept)
     925             : {
     926             :   while (*s != '\0')
     927             :     {
     928             :       const char *a = accept;
     929             :       while (*a != '\0')
     930             :         if (*a++ == *s)
     931             :           return (char *) s;
     932             :       ++s;
     933             :     }
     934             : 
     935             :   return NULL;
     936             : }
     937             : #endif /*!HAVE_STRPBRK*/
     938             : 
     939             : 
     940             : #ifndef HAVE_STRSEP
     941             : /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
     942             : char *
     943             : strsep (char **stringp, const char *delim)
     944             : {
     945             :   char *begin, *end;
     946             : 
     947             :   begin = *stringp;
     948             :   if (begin == NULL)
     949             :     return NULL;
     950             : 
     951             :   /* A frequent case is when the delimiter string contains only one
     952             :      character.  Here we don't need to call the expensive 'strpbrk'
     953             :      function and instead work using 'strchr'.  */
     954             :   if (delim[0] == '\0' || delim[1] == '\0')
     955             :     {
     956             :       char ch = delim[0];
     957             : 
     958             :       if (ch == '\0')
     959             :         end = NULL;
     960             :       else
     961             :         {
     962             :           if (*begin == ch)
     963             :             end = begin;
     964             :           else if (*begin == '\0')
     965             :             end = NULL;
     966             :           else
     967             :             end = strchr (begin + 1, ch);
     968             :         }
     969             :     }
     970             :   else
     971             :     /* Find the end of the token.  */
     972             :     end = strpbrk (begin, delim);
     973             : 
     974             :   if (end)
     975             :     {
     976             :       /* Terminate the token and set *STRINGP past NUL character.  */
     977             :       *end++ = '\0';
     978             :       *stringp = end;
     979             :     }
     980             :   else
     981             :     /* No more delimiters; this is the last token.  */
     982             :     *stringp = NULL;
     983             : 
     984             :   return begin;
     985             : }
     986             : #endif /*HAVE_STRSEP*/
     987             : 
     988             : 
     989             : #ifndef HAVE_STRLWR
     990             : char *
     991          28 : strlwr(char *s)
     992             : {
     993             :     char *p;
     994         596 :     for(p=s; *p; p++ )
     995         568 :         *p = tolower(*p);
     996          28 :     return s;
     997             : }
     998             : #endif
     999             : 
    1000             : 
    1001             : #ifndef HAVE_STRCASECMP
    1002             : int
    1003             : strcasecmp( const char *a, const char *b )
    1004             : {
    1005             :     for( ; *a && *b; a++, b++ ) {
    1006             :         if( *a != *b && toupper(*a) != toupper(*b) )
    1007             :             break;
    1008             :     }
    1009             :     return *(const byte*)a - *(const byte*)b;
    1010             : }
    1011             : #endif
    1012             : 
    1013             : 
    1014             : /****************
    1015             :  * mingw32/cpd has a memicmp()
    1016             :  */
    1017             : #ifndef HAVE_MEMICMP
    1018             : int
    1019           2 : memicmp( const char *a, const char *b, size_t n )
    1020             : {
    1021          32 :     for( ; n; n--, a++, b++ )
    1022          30 :         if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
    1023           0 :             return *(const byte *)a - *(const byte*)b;
    1024           2 :     return 0;
    1025             : }
    1026             : #endif
    1027             : 
    1028             : 
    1029             : #ifndef HAVE_MEMRCHR
    1030             : void *
    1031             : memrchr (const void *buffer, int c, size_t n)
    1032             : {
    1033             :   const unsigned char *p = buffer;
    1034             : 
    1035             :   for (p += n; n ; n--)
    1036             :     if (*--p == c)
    1037             :       return (void *)p;
    1038             :   return NULL;
    1039             : }
    1040             : #endif /*HAVE_MEMRCHR*/
    1041             : 
    1042             : 
    1043             : /* Percent-escape the string STR by replacing colons with '%3a'.  If
    1044             :    EXTRA is not NULL all characters in EXTRA are also escaped.  */
    1045             : static char *
    1046          24 : do_percent_escape (const char *str, const char *extra, int die)
    1047             : {
    1048             :   int i, j;
    1049             :   char *ptr;
    1050             : 
    1051          24 :   if (!str)
    1052           1 :     return NULL;
    1053             : 
    1054         179 :   for (i=j=0; str[i]; i++)
    1055         156 :     if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
    1056          40 :       j++;
    1057          23 :   if (die)
    1058          21 :     ptr = xmalloc (i + 2 * j + 1);
    1059             :   else
    1060             :     {
    1061           2 :       ptr = xtrymalloc (i + 2 * j + 1);
    1062           2 :       if (!ptr)
    1063           0 :         return NULL;
    1064             :     }
    1065          23 :   i = 0;
    1066         202 :   while (*str)
    1067             :     {
    1068         156 :       if (*str == ':')
    1069             :         {
    1070          20 :           ptr[i++] = '%';
    1071          20 :           ptr[i++] = '3';
    1072          20 :           ptr[i++] = 'a';
    1073             :         }
    1074         136 :       else if (*str == '%')
    1075             :         {
    1076          15 :           ptr[i++] = '%';
    1077          15 :           ptr[i++] = '2';
    1078          15 :           ptr[i++] = '5';
    1079             :         }
    1080         121 :       else if (extra && strchr (extra, *str))
    1081             :         {
    1082           5 :           ptr[i++] = '%';
    1083           5 :           ptr[i++] = tohex_lower ((*str>>4)&15);
    1084           5 :           ptr[i++] = tohex_lower (*str&15);
    1085             :         }
    1086             :       else
    1087         116 :         ptr[i++] = *str;
    1088         156 :       str++;
    1089             :     }
    1090          23 :   ptr[i] = '\0';
    1091             : 
    1092          23 :   return ptr;
    1093             : }
    1094             : 
    1095             : /* Percent-escape the string STR by replacing colons with '%3a'.  If
    1096             :    EXTRA is not NULL all characters in EXTRA are also escaped.  This
    1097             :    function terminates the process on memory shortage.  */
    1098             : char *
    1099          22 : percent_escape (const char *str, const char *extra)
    1100             : {
    1101          22 :   return do_percent_escape (str, extra, 1);
    1102             : }
    1103             : 
    1104             : /* Same as percent_escape but return NULL instead of exiting on memory
    1105             :    error. */
    1106             : char *
    1107           2 : try_percent_escape (const char *str, const char *extra)
    1108             : {
    1109           2 :   return do_percent_escape (str, extra, 0);
    1110             : }
    1111             : 
    1112             : 
    1113             : 
    1114             : static char *
    1115        2187 : do_strconcat (const char *s1, va_list arg_ptr)
    1116             : {
    1117             :   const char *argv[48];
    1118             :   size_t argc;
    1119             :   size_t needed;
    1120             :   char *buffer, *p;
    1121             : 
    1122        2187 :   argc = 0;
    1123        2187 :   argv[argc++] = s1;
    1124        2187 :   needed = strlen (s1);
    1125        8883 :   while (((argv[argc] = va_arg (arg_ptr, const char *))))
    1126             :     {
    1127        4511 :       needed += strlen (argv[argc]);
    1128        4511 :       if (argc >= DIM (argv)-1)
    1129             :         {
    1130           2 :           gpg_err_set_errno (EINVAL);
    1131           2 :           return NULL;
    1132             :         }
    1133        4509 :       argc++;
    1134             :     }
    1135        2185 :   needed++;
    1136        2185 :   buffer = xtrymalloc (needed);
    1137        2185 :   if (buffer)
    1138             :     {
    1139        8787 :       for (p = buffer, argc=0; argv[argc]; argc++)
    1140        6602 :         p = stpcpy (p, argv[argc]);
    1141             :     }
    1142        2185 :   return buffer;
    1143             : }
    1144             : 
    1145             : 
    1146             : /* Concatenate the string S1 with all the following strings up to a
    1147             :    NULL.  Returns a malloced buffer with the new string or NULL on a
    1148             :    malloc error or if too many arguments are given.  */
    1149             : char *
    1150        2134 : strconcat (const char *s1, ...)
    1151             : {
    1152             :   va_list arg_ptr;
    1153             :   char *result;
    1154             : 
    1155        2134 :   if (!s1)
    1156           1 :     result = xtrystrdup ("");
    1157             :   else
    1158             :     {
    1159        2133 :       va_start (arg_ptr, s1);
    1160        2133 :       result = do_strconcat (s1, arg_ptr);
    1161        2133 :       va_end (arg_ptr);
    1162             :     }
    1163        2134 :   return result;
    1164             : }
    1165             : 
    1166             : /* Same as strconcat but terminate the process with an error message
    1167             :    if something goes wrong.  */
    1168             : char *
    1169          55 : xstrconcat (const char *s1, ...)
    1170             : {
    1171             :   va_list arg_ptr;
    1172             :   char *result;
    1173             : 
    1174          55 :   if (!s1)
    1175           1 :     result = xstrdup ("");
    1176             :   else
    1177             :     {
    1178          54 :       va_start (arg_ptr, s1);
    1179          54 :       result = do_strconcat (s1, arg_ptr);
    1180          54 :       va_end (arg_ptr);
    1181             :     }
    1182          55 :   if (!result)
    1183             :     {
    1184           0 :       if (errno == EINVAL)
    1185           0 :         fputs ("\nfatal: too many args for xstrconcat\n", stderr);
    1186             :       else
    1187           0 :         fputs ("\nfatal: out of memory\n", stderr);
    1188           0 :       exit (2);
    1189             :     }
    1190          55 :   return result;
    1191             : }
    1192             : 
    1193             : /* Split a string into fields at DELIM.  REPLACEMENT is the character
    1194             :    to replace the delimiter with (normally: '\0' so that each field is
    1195             :    NUL terminated).  The caller is responsible for freeing the result.
    1196             :    Note: this function modifies STRING!  If you need the original
    1197             :    value, then you should pass a copy to this function.
    1198             : 
    1199             :    If malloc fails, this function returns NULL.  */
    1200             : char **
    1201           3 : strsplit (char *string, char delim, char replacement, int *count)
    1202             : {
    1203           3 :   int fields = 1;
    1204             :   char *t;
    1205             :   char **result;
    1206             : 
    1207             :   /* First, count the number of fields.  */
    1208          15 :   for (t = strchr (string, delim); t; t = strchr (t + 1, delim))
    1209          12 :     fields ++;
    1210             : 
    1211           3 :   result = xtrycalloc ((fields + 1), sizeof (*result));
    1212           3 :   if (! result)
    1213           0 :     return NULL;
    1214             : 
    1215           3 :   result[0] = string;
    1216           3 :   fields = 1;
    1217          15 :   for (t = strchr (string, delim); t; t = strchr (t + 1, delim))
    1218             :     {
    1219          12 :       result[fields ++] = t + 1;
    1220          12 :       *t = replacement;
    1221             :     }
    1222             : 
    1223           3 :   if (count)
    1224           3 :     *count = fields;
    1225             : 
    1226           3 :   return result;
    1227             : }
    1228             : 
    1229             : 
    1230             : /* Tokenize STRING using the set of delimiters in DELIM.  Leading
    1231             :  * spaces and tabs are removed from all tokens.  The caller must xfree
    1232             :  * the result.
    1233             :  *
    1234             :  * Returns: A malloced and NULL delimited array with the tokens.  On
    1235             :  *          memory error NULL is returned and ERRNO is set.
    1236             :  */
    1237             : char **
    1238          25 : strtokenize (const char *string, const char *delim)
    1239             : {
    1240             :   const char *s;
    1241             :   size_t fields;
    1242             :   size_t bytes, n;
    1243             :   char *buffer;
    1244             :   char *p, *px, *pend;
    1245             :   char **result;
    1246             : 
    1247             :   /* Count the number of fields.  */
    1248          67 :   for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
    1249          42 :     fields++;
    1250          25 :   fields++; /* Add one for the terminating NULL.  */
    1251             : 
    1252             :   /* Allocate an array for all fields, a terminating NULL, and space
    1253             :      for a copy of the string.  */
    1254          25 :   bytes = fields * sizeof *result;
    1255          25 :   if (bytes / sizeof *result != fields)
    1256             :     {
    1257           0 :       gpg_err_set_errno (ENOMEM);
    1258           0 :       return NULL;
    1259             :     }
    1260          25 :   n = strlen (string) + 1;
    1261          25 :   bytes += n;
    1262          25 :   if (bytes < n)
    1263             :     {
    1264           0 :       gpg_err_set_errno (ENOMEM);
    1265           0 :       return NULL;
    1266             :     }
    1267          25 :   result = xtrymalloc (bytes);
    1268          25 :   if (!result)
    1269           0 :     return NULL;
    1270          25 :   buffer = (char*)(result + fields);
    1271             : 
    1272             :   /* Copy and parse the string.  */
    1273          25 :   strcpy (buffer, string);
    1274          67 :   for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
    1275             :     {
    1276          42 :       *pend = 0;
    1277          98 :       while (spacep (p))
    1278          14 :         p++;
    1279          42 :       for (px = pend - 1; px >= p && spacep (px); px--)
    1280           0 :         *px = 0;
    1281          42 :       result[n++] = p;
    1282             :     }
    1283          57 :   while (spacep (p))
    1284           7 :     p++;
    1285          28 :   for (px = p + strlen (p) - 1; px >= p && spacep (px); px--)
    1286           3 :     *px = 0;
    1287          25 :   result[n++] = p;
    1288          25 :   result[n] = NULL;
    1289             : 
    1290          25 :   assert ((char*)(result + n + 1) == buffer);
    1291             : 
    1292          25 :   return result;
    1293             : }
    1294             : 
    1295             : 
    1296             : /* Split a string into space delimited fields and remove leading and
    1297             :  * trailing spaces from each field.  A pointer to each field is stored
    1298             :  * in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
    1299             :  * modifies STRING.  The number of parsed fields is returned.
    1300             :  * Example:
    1301             :  *
    1302             :  *   char *fields[2];
    1303             :  *   if (split_fields (string, fields, DIM (fields)) < 2)
    1304             :  *     return  // Not enough args.
    1305             :  *   foo (fields[0]);
    1306             :  *   foo (fields[1]);
    1307             :  */
    1308             : int
    1309          65 : split_fields (char *string, char **array, int arraysize)
    1310             : {
    1311          65 :   int n = 0;
    1312             :   char *p, *pend;
    1313             : 
    1314          65 :   for (p = string; *p == ' '; p++)
    1315             :     ;
    1316             :   do
    1317             :     {
    1318         436 :       if (n == arraysize)
    1319          62 :         break;
    1320         374 :       array[n++] = p;
    1321         374 :       pend = strchr (p, ' ');
    1322         374 :       if (!pend)
    1323           0 :         break;
    1324         374 :       *pend++ = 0;
    1325         374 :       for (p = pend; *p == ' '; p++)
    1326             :         ;
    1327             :     }
    1328         374 :   while (*p);
    1329             : 
    1330          65 :   return n;
    1331             : }
    1332             : 
    1333             : 
    1334             : 
    1335             : /* Version number parsing.  */
    1336             : 
    1337             : /* This function parses the first portion of the version number S and
    1338             :    stores it in *NUMBER.  On success, this function returns a pointer
    1339             :    into S starting with the first character, which is not part of the
    1340             :    initial number portion; on failure, NULL is returned.  */
    1341             : static const char*
    1342        3426 : parse_version_number (const char *s, int *number)
    1343             : {
    1344        3426 :   int val = 0;
    1345             : 
    1346        3426 :   if (*s == '0' && digitp (s+1))
    1347           0 :     return NULL;  /* Leading zeros are not allowed.  */
    1348        7914 :   for (; digitp (s); s++)
    1349             :     {
    1350        4488 :       val *= 10;
    1351        4488 :       val += *s - '0';
    1352             :     }
    1353        3426 :   *number = val;
    1354        3426 :   return val < 0 ? NULL : s;
    1355             : }
    1356             : 
    1357             : 
    1358             : /* This function breaks up the complete string-representation of the
    1359             :    version number S, which is of the following struture: <major
    1360             :    number>.<minor number>[.<micro number>]<patch level>.  The major,
    1361             :    minor, and micro number components will be stored in *MAJOR, *MINOR
    1362             :    and *MICRO.  If MICRO is not given 0 is used instead.
    1363             : 
    1364             :    On success, the last component, the patch level, will be returned;
    1365             :    in failure, NULL will be returned.  */
    1366             : static const char *
    1367        1149 : parse_version_string (const char *s, int *major, int *minor, int *micro)
    1368             : {
    1369        1149 :   s = parse_version_number (s, major);
    1370        1149 :   if (!s || *s != '.')
    1371           6 :     return NULL;
    1372        1143 :   s++;
    1373        1143 :   s = parse_version_number (s, minor);
    1374        1143 :   if (!s)
    1375           0 :     return NULL;
    1376        1143 :   if (*s == '.')
    1377             :     {
    1378        1134 :       s++;
    1379        1134 :       s = parse_version_number (s, micro);
    1380        1134 :       if (!s)
    1381           0 :         return NULL;
    1382             :     }
    1383             :   else
    1384           9 :     *micro = 0;
    1385        1143 :   return s;  /* Patchlevel.  */
    1386             : }
    1387             : 
    1388             : 
    1389             : /* Compare the version string MY_VERSION to the version string
    1390             :  * REQ_VERSION.  Returns -1, 0, or 1 if MY_VERSION is found,
    1391             :  * respectively, to be less than, to match, or be greater than
    1392             :  * REQ_VERSION.  This function works for three and two part version
    1393             :  * strings; for a two part version string the micro part is assumed to
    1394             :  * be 0.  Patch levels are compared as strings.  If a version number
    1395             :  * is invalid INT_MIN is returned.  If REQ_VERSION is given as NULL
    1396             :  * the function returns 0 if MY_VERSION is parsable version string. */
    1397             : int
    1398         580 : compare_version_strings (const char *my_version, const char *req_version)
    1399             : {
    1400             :   int my_major, my_minor, my_micro;
    1401             :   int rq_major, rq_minor, rq_micro;
    1402             :   const char *my_patch, *rq_patch;
    1403             :   int result;
    1404             : 
    1405         580 :   if (!my_version)
    1406           2 :     return INT_MIN;
    1407             : 
    1408         578 :   my_patch = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
    1409         578 :   if (!my_patch)
    1410           4 :     return INT_MIN;
    1411         574 :   if (!req_version)
    1412           3 :     return 0; /* MY_VERSION can be parsed.  */
    1413         571 :   rq_patch = parse_version_string (req_version, &rq_major, &rq_minor,&rq_micro);
    1414         571 :   if (!rq_patch)
    1415           2 :     return INT_MIN;
    1416             : 
    1417         569 :   if (my_major == rq_major)
    1418             :     {
    1419         568 :       if (my_minor == rq_minor)
    1420             :         {
    1421         558 :           if (my_micro == rq_micro)
    1422         549 :             result = strcmp (my_patch, rq_patch);
    1423             :           else
    1424           9 :             result = my_micro - rq_micro;
    1425             :         }
    1426             :       else
    1427          10 :         result = my_minor - rq_minor;
    1428             :     }
    1429             :   else
    1430           1 :     result = my_major - rq_major;
    1431             : 
    1432         569 :   return !result? 0 : result < 0 ? -1 : 1;
    1433             : }
    1434             : 
    1435             : 
    1436             : 
    1437             : /* Format a string so that it fits within about TARGET_COLS columns.
    1438             :    If IN_PLACE is 0, then TEXT is copied to a new buffer, which is
    1439             :    returned.  Otherwise, TEXT is modified in place and returned.
    1440             :    Normally, target_cols will be 72 and max_cols is 80.  */
    1441             : char *
    1442          54 : format_text (char *text, int in_place, int target_cols, int max_cols)
    1443             : {
    1444          54 :   const int do_debug = 0;
    1445             : 
    1446             :   /* The character under consideration.  */
    1447             :   char *p;
    1448             :   /* The start of the current line.  */
    1449             :   char *line;
    1450             :   /* The last space that we saw.  */
    1451          54 :   char *last_space = NULL;
    1452          54 :   int last_space_cols = 0;
    1453          54 :   int copied_last_space = 0;
    1454             : 
    1455          54 :   if (! in_place)
    1456          54 :     text = xstrdup (text);
    1457             : 
    1458          54 :   p = line = text;
    1459             :   while (1)
    1460             :     {
    1461             :       /* The number of columns including any trailing space.  */
    1462             :       int cols;
    1463             : 
    1464        1354 :       p = p + strcspn (p, "\n ");
    1465        1354 :       if (! p)
    1466             :         /* P now points to the NUL character.  */
    1467           0 :         p = &text[strlen (text)];
    1468             : 
    1469        1354 :       if (*p == '\n')
    1470             :         /* Pass through any newlines.  */
    1471             :         {
    1472          81 :           p ++;
    1473          81 :           line = p;
    1474          81 :           last_space = NULL;
    1475          81 :           last_space_cols = 0;
    1476          81 :           copied_last_space = 1;
    1477          81 :           continue;
    1478             :         }
    1479             : 
    1480             :       /* Have a space or a NUL.  Note: we don't count the trailing
    1481             :          space.  */
    1482        1273 :       cols = utf8_charcount (line, (uintptr_t) p - (uintptr_t) line);
    1483        1273 :       if (cols < target_cols)
    1484             :         {
    1485        1198 :           if (! *p)
    1486             :             /* Nothing left to break.  */
    1487          54 :             break;
    1488             : 
    1489        1144 :           last_space = p;
    1490        1144 :           last_space_cols = cols;
    1491        1144 :           p ++;
    1492             :           /* Skip any immediately following spaces.  If we break:
    1493             :              "... foo bar ..." between "foo" and "bar" then we want:
    1494             :              "... foo\nbar ...", which means that the left space has
    1495             :              to be the first space after foo, not the last space
    1496             :              before bar.  */
    1497        2351 :           while (*p == ' ')
    1498          63 :             p ++;
    1499             :         }
    1500             :       else
    1501             :         {
    1502             :           int cols_with_left_space;
    1503             :           int cols_with_right_space;
    1504             :           int left_penalty;
    1505             :           int right_penalty;
    1506             : 
    1507          75 :           cols_with_left_space = last_space_cols;
    1508          75 :           cols_with_right_space = cols;
    1509             : 
    1510          75 :           if (do_debug)
    1511           0 :             log_debug ("Breaking: '%.*s'\n",
    1512           0 :                        (int) ((uintptr_t) p - (uintptr_t) line), line);
    1513             : 
    1514             :           /* The number of columns away from TARGET_COLS.  We prefer
    1515             :              to underflow than to overflow.  */
    1516          75 :           left_penalty = target_cols - cols_with_left_space;
    1517          75 :           right_penalty = 2 * (cols_with_right_space - target_cols);
    1518             : 
    1519          75 :           if (cols_with_right_space > max_cols)
    1520             :             /* Add a large penalty for each column that exceeds
    1521             :                max_cols.  */
    1522           1 :             right_penalty += 4 * (cols_with_right_space - max_cols);
    1523             : 
    1524          75 :           if (do_debug)
    1525           0 :             log_debug ("Left space => %d cols (penalty: %d); right space => %d cols (penalty: %d)\n",
    1526             :                        cols_with_left_space, left_penalty,
    1527             :                        cols_with_right_space, right_penalty);
    1528          75 :           if (last_space_cols && left_penalty <= right_penalty)
    1529             :             /* Prefer the left space.  */
    1530             :             {
    1531          37 :               if (do_debug)
    1532           0 :                 log_debug ("Breaking at left space.\n");
    1533          37 :               p = last_space;
    1534             :             }
    1535             :           else
    1536             :             {
    1537          38 :               if (do_debug)
    1538           0 :                 log_debug ("Breaking at right space.\n");
    1539             :             }
    1540             : 
    1541          75 :           if (! *p)
    1542           0 :             break;
    1543             : 
    1544          75 :           *p = '\n';
    1545          75 :           p ++;
    1546          75 :           if (*p == ' ')
    1547             :             {
    1548             :               int spaces;
    1549           5 :               for (spaces = 1; p[spaces] == ' '; spaces ++)
    1550             :                 ;
    1551           5 :               memmove (p, &p[spaces], strlen (&p[spaces]) + 1);
    1552             :             }
    1553          75 :           line = p;
    1554          75 :           last_space = NULL;
    1555          75 :           last_space_cols = 0;
    1556          75 :           copied_last_space = 0;
    1557             :         }
    1558        1300 :     }
    1559             : 
    1560             :   /* Chop off any trailing space.  */
    1561          54 :   trim_trailing_chars (text, strlen (text), " ");
    1562             :   /* If we inserted the trailing newline, then remove it.  */
    1563          54 :   if (! copied_last_space && *text && text[strlen (text) - 1] == '\n')
    1564           0 :     text[strlen (text) - 1] = '\0';
    1565             : 
    1566          54 :   return text;
    1567             : }

Generated by: LCOV version 1.11