LCOV - code coverage report
Current view: top level - src - argcv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 190 0.0 %
Date: 2015-04-20 Functions: 0 10 0.0 %

          Line data    Source code
       1             : /* argcv.c - simple functions for parsing input based on whitespace
       2             :    Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
       3             : 
       4             :    This library is free software; you can redistribute it and/or
       5             :    modify it under the terms of the GNU Lesser General Public
       6             :    License as published by the Free Software Foundation; either
       7             :    version 3 of the License, or (at your option) any later version.
       8             : 
       9             :    This library is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :    Lesser General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU Lesser General
      15             :    Public License along with this library; if not, write to the
      16             :    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      17             :    Boston, MA 02110-1301 USA */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : # include <config.h>
      21             : #endif
      22             : 
      23             : #include <ctype.h>
      24             : #include <errno.h>
      25             : #include <argcv.h>
      26             : 
      27             : /*
      28             :  * takes a string and splits it into several strings, breaking at ' '
      29             :  * command is the string to split
      30             :  * the number of strings is placed into argc
      31             :  * the split strings are put into argv
      32             :  * returns 0 on success, nonzero on failure
      33             :  */
      34             : 
      35             : #define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
      36             : #define isdelim(c,delim) (strchr(delim,(c))!=NULL)
      37             : 
      38             : static int
      39           0 : argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
      40             :             int *start, int *end, int *save)
      41             : {
      42           0 :   int i = 0;
      43             :   
      44             :   for (;;)
      45             :     {
      46           0 :       i = *save;
      47             : 
      48           0 :       if (i >= len)
      49           0 :         return i + 1;
      50             : 
      51             :       /* Skip initial whitespace */
      52           0 :       while (i < len && isws (command[i]))
      53           0 :         i++;
      54           0 :       *start = i;
      55             : 
      56           0 :       if (!isdelim (command[i], delim))
      57             :         {
      58           0 :           while (i < len)
      59             :             {
      60           0 :               if (command[i] == '\\')
      61             :                 {
      62           0 :                   if (++i == len)
      63           0 :                     break;
      64           0 :                   i++;
      65           0 :                   continue;
      66             :                 }
      67             :               
      68           0 :               if (command[i] == '\'' || command[i] == '"')
      69           0 :                 {
      70             :                   int j;
      71           0 :                   for (j = i+1; j < len && command[j] != command[i]; j++)
      72           0 :                     if (command[j] == '\\')
      73           0 :                       j++;
      74           0 :                   if (j < len)
      75           0 :                     i = j+1;
      76             :                   else
      77           0 :                     i++;
      78             :                 }
      79           0 :               else if (isws (command[i]) || isdelim (command[i], delim))
      80             :                 break;
      81             :               else
      82           0 :                 i++; /* skip the escaped character */
      83             :             }
      84           0 :           i--;
      85             :         }
      86             : 
      87           0 :       *end = i;
      88           0 :       *save = i + 1;
      89             : 
      90             :       /* If we have a token, and it starts with a comment character, skip
      91             :          to the newline and restart the token search. */
      92           0 :       if (*save <= len)
      93             :         {
      94           0 :           if (cmnt && strchr (cmnt, command[*start]) != NULL)
      95             :             {
      96           0 :               i = *save;
      97           0 :               while (i < len && command[i] != '\n')
      98           0 :                 i++;
      99             : 
     100           0 :               *save = i;
     101           0 :               continue;
     102             :             }
     103             :         }
     104           0 :       break;
     105           0 :     }
     106           0 :   return *save;
     107             : }
     108             : 
     109             : static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
     110             : 
     111             : int
     112           0 : argcv_unquote_char (int c)
     113             : {
     114             :   char *p;
     115             : 
     116           0 :   for (p = quote_transtab; *p; p += 2)
     117             :     {
     118           0 :       if (*p == c)
     119           0 :         return p[1];
     120             :     }
     121           0 :   return c;
     122             : }
     123             : 
     124             : int
     125           0 : argcv_quote_char (int c)
     126             : {
     127             :   char *p;
     128             :   
     129           0 :   for (p = quote_transtab + sizeof(quote_transtab) - 2;
     130           0 :        p > quote_transtab; p -= 2)
     131             :     {
     132           0 :       if (*p == c)
     133           0 :         return p[-1];
     134             :     }
     135           0 :   return -1;
     136             : }
     137             :   
     138             : #define to_num(c) \
     139             :   (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
     140             : 
     141             : static int
     142           0 : xtonum (int *pval, const char *src, int base, int cnt)
     143             : {
     144             :   int i, val;
     145             :   
     146           0 :   for (i = 0, val = 0; i < cnt; i++, src++)
     147             :     {
     148           0 :       int n = *(unsigned char*)src;
     149           0 :       if (n > 127 || (n = to_num(n)) >= base)
     150             :         break;
     151           0 :       val = val*base + n;
     152             :     }
     153           0 :   *pval = val;
     154           0 :   return i;
     155             : }
     156             : 
     157             : size_t
     158           0 : argcv_quoted_length (const char *str, int *quote)
     159             : {
     160           0 :   size_t len = 0;
     161             : 
     162           0 :   *quote = 0;
     163           0 :   for (; *str; str++)
     164             :     {
     165           0 :       if (*str == ' ')
     166             :         {
     167           0 :           len++;
     168           0 :           *quote = 1;
     169             :         }
     170           0 :       else if (*str == '"' || *str == '\'')
     171             :         {
     172           0 :           len += 2;
     173           0 :           *quote = 1;
     174             :         }
     175           0 :       else if (*str != '\t' && *str != '\\' && isprint (*str))
     176           0 :         len++;
     177           0 :       else if (argcv_quote_char (*str) != -1)
     178           0 :         len += 2;
     179             :       else
     180           0 :         len += 4;
     181             :     }
     182           0 :   return len;
     183             : }
     184             : 
     185             : void
     186           0 : argcv_unquote_copy (char *dst, const char *src, size_t n)
     187             : {
     188           0 :   int i = 0;
     189             :   int c;
     190           0 :   int expect_delim = 0; 
     191             :     
     192           0 :   while (i < n)
     193             :     {
     194           0 :       switch (src[i])
     195             :         {
     196             :         case '\'':
     197             :         case '"':
     198           0 :           if (!expect_delim)
     199             :             {
     200             :               const char *p;
     201             :               
     202           0 :               for (p = src+i+1; *p && *p != src[i]; p++)
     203           0 :                 if (*p == '\\')
     204           0 :                   p++;
     205           0 :               if (*p)
     206           0 :                 expect_delim = src[i++];
     207             :               else
     208           0 :                 *dst++ = src[i++];
     209             :             }
     210           0 :           else if (expect_delim == src[i])
     211           0 :             ++i;
     212             :           else
     213           0 :             *dst++ = src[i++];
     214           0 :           break;
     215             :           
     216             :         case '\\':
     217           0 :           ++i;
     218           0 :           if (src[i] == 'x' || src[i] == 'X')
     219             :             {
     220           0 :               if (n - i < 2)
     221             :                 {
     222           0 :                   *dst++ = '\\';
     223           0 :                   *dst++ = src[i++];
     224             :                 }
     225             :               else 
     226             :                 {
     227           0 :                   int off = xtonum(&c, src + i + 1, 16, 2);
     228           0 :                   if (off == 0)
     229             :                     {
     230           0 :                       *dst++ = '\\';
     231           0 :                       *dst++ = src[i++];
     232             :                     }
     233             :                   else
     234             :                     {
     235           0 :                       *dst++ = c;
     236           0 :                       i += off + 1;
     237             :                     }
     238             :                 }
     239             :             }
     240           0 :           else if ((unsigned char)src[i] < 128 && isdigit(src[i]))
     241             :             {
     242           0 :               if (n - i < 1)
     243             :                 {
     244           0 :                   *dst++ = '\\';
     245           0 :                   *dst++ = src[i++];
     246             :                 }
     247             :               else
     248             :                 {
     249           0 :                   int off = xtonum(&c, src+i, 8, 3);
     250           0 :                   if (off == 0)
     251             :                     {
     252           0 :                       *dst++ = '\\';
     253           0 :                       *dst++ = src[i++];
     254             :                     }
     255             :                   else
     256             :                     {
     257           0 :                       *dst++ = c;
     258           0 :                       i += off;
     259             :                     }
     260             :                 }
     261             :             }
     262             :           else
     263           0 :             *dst++ = argcv_unquote_char (src[i++]);
     264           0 :           break;
     265             :           
     266             :         default:
     267           0 :           *dst++ = src[i++];
     268             :         }
     269             :     }
     270           0 :   *dst = 0;
     271           0 : }
     272             : 
     273             : void
     274           0 : argcv_quote_copy (char *dst, const char *src)
     275             : {
     276           0 :   for (; *src; src++)
     277             :     {
     278           0 :       if (*src == '"' || *src == '\'')
     279             :         {
     280           0 :           *dst++ = '\\';
     281           0 :           *dst++ = *src;
     282             :         }
     283           0 :       else if (*src != '\t' && *src != '\\' && isprint(*src))
     284           0 :         *dst++ = *src;      
     285             :       else
     286             :         {
     287           0 :           int c = argcv_quote_char (*src);
     288           0 :           *dst++ = '\\';
     289           0 :           if (c != -1)
     290           0 :             *dst++ = c;
     291             :           else
     292             :             {
     293             :               char tmp[4];
     294           0 :               snprintf (tmp, sizeof tmp, "%03o", *(unsigned char*)src);
     295           0 :               memcpy (dst, tmp, 3);
     296           0 :               dst += 3;
     297             :             }
     298             :         }
     299             :     }
     300           0 : }
     301             : 
     302             : int
     303           0 : argcv_get (const char *command, const char *delim, const char *cmnt,
     304             :            int *argc, char ***argv)
     305             : {
     306           0 :   int len = strlen (command);
     307           0 :   int i = 0;
     308             :   int start, end, save;
     309             : 
     310           0 :   *argv = NULL;
     311             : 
     312             :   /* Count number of arguments */
     313           0 :   *argc = 0;
     314           0 :   save = 0;
     315             : 
     316           0 :   while (argcv_scan (len, command, delim, cmnt, &start, &end, &save) <= len)
     317           0 :       (*argc)++;
     318             : 
     319           0 :   *argv = calloc ((*argc + 1), sizeof (char *));
     320           0 :   if (*argv == NULL)
     321           0 :     return ENOMEM;
     322             :   
     323           0 :   i = 0;
     324           0 :   save = 0;
     325           0 :   for (i = 0; i < *argc; i++)
     326             :     {
     327             :       int n;
     328           0 :       argcv_scan (len, command, delim, cmnt, &start, &end, &save);
     329             : 
     330           0 :       if ((command[start] == '"' || command[end] == '\'')
     331           0 :           && command[end] == command[start])
     332             :         {
     333           0 :           start++;
     334           0 :           end--;
     335             :         }
     336           0 :       n = end - start + 1;
     337           0 :       (*argv)[i] = calloc (n+1,  sizeof (char));
     338           0 :       if ((*argv)[i] == NULL)
     339           0 :         return ENOMEM;
     340           0 :       argcv_unquote_copy ((*argv)[i], &command[start], n);
     341           0 :       (*argv)[i][n] = 0;
     342             :     }
     343           0 :   (*argv)[i] = NULL;
     344           0 :   return 0;
     345             : }
     346             : 
     347             : /*
     348             :  * frees all elements of an argv array
     349             :  * argc is the number of elements
     350             :  * argv is the array
     351             :  */
     352             : int
     353           0 : argcv_free (int argc, char **argv)
     354             : {
     355           0 :   while (--argc >= 0)
     356           0 :     if (argv[argc])
     357           0 :       free (argv[argc]);
     358           0 :   free (argv);
     359           0 :   return 0;
     360             : }
     361             : 
     362             : /* Take a argv an make string separated by ' '.  */
     363             : 
     364             : int
     365           0 : argcv_string (int argc, char **argv, char **pstring)
     366             : {
     367             :   size_t i, j, len;
     368             :   char *buffer;
     369             : 
     370             :   /* No need.  */
     371           0 :   if (pstring == NULL)
     372           0 :     return EINVAL;
     373             : 
     374           0 :   buffer = malloc (1);
     375           0 :   if (buffer == NULL)
     376           0 :     return ENOMEM;
     377           0 :   *buffer = '\0';
     378             : 
     379           0 :   for (len = i = j = 0; i < argc; i++)
     380             :     {
     381             :       int quote;
     382             :       int toklen;
     383             : 
     384           0 :       toklen = argcv_quoted_length (argv[i], &quote);
     385             :       
     386           0 :       len += toklen + 2;
     387           0 :       if (quote)
     388           0 :         len += 2;
     389             :       
     390           0 :       buffer = realloc (buffer, len);
     391           0 :       if (buffer == NULL)
     392           0 :         return ENOMEM;
     393             : 
     394           0 :       if (i != 0)
     395           0 :         buffer[j++] = ' ';
     396           0 :       if (quote)
     397           0 :         buffer[j++] = '"';
     398           0 :       argcv_quote_copy (buffer + j, argv[i]);
     399           0 :       j += toklen;
     400           0 :       if (quote)
     401           0 :         buffer[j++] = '"';
     402             :     }
     403             : 
     404           0 :   for (; j > 0 && isspace (buffer[j-1]); j--)
     405             :     ;
     406           0 :   buffer[j] = 0;
     407           0 :   if (pstring)
     408           0 :     *pstring = buffer;
     409           0 :   return 0;
     410             : }
     411             : 

Generated by: LCOV version 1.10