Edit

kc3-lang/pkgconf/argvsplit.c

Branch :

  • Show log

    Commit

  • Author : William Pitcock
    Date : 2012-05-05 17:44:24
    Hash : 5460704d
    Message : argvsplit: slightly change strategy for splitting arguments

  • argvsplit.c
  • /*
     * argvsplit.c
     * argv_split() routine
     *
     * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
     *
     * Permission to use, copy, modify, and/or distribute this software for any
     * purpose with or without fee is hereby granted, provided that the above
     * copyright notice and this permission notice appear in all copies.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     * POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include "config.h"
    #include "pkg.h"
    
    int argv_split(const char *src, int *argc, char ***argv)
    {
    	char *buf = malloc(strlen(src) + 1);
    	const char *src_iter;
    	char *dst_iter;
    	int argc_count = 0;
    	int argv_size = 5;
    	char quote = 0;
    
    	src_iter = src;
    	dst_iter = buf;
    
    	bzero(buf, strlen(src) + 1);
    
    	*argv = calloc(sizeof (void *), argv_size);
    	(*argv)[argc_count] = dst_iter;
    
    	while (*src_iter)
    	{
    		if (quote == *src_iter)
    			quote = 0;
    		else if (quote)
    		{
    			if (*src_iter == '\\')
    			{
    				src_iter++;
    				if (!*src_iter)
    				{
    					free(*argv);
    					free(buf);
    					return -1;
    				}
    
    				if (*src_iter != quote)
    					*dst_iter++ = '\\';
    			}
    			*dst_iter++ = *src_iter;
    		}
    		else if (isspace(*src_iter))
    		{
    			if (*(src_iter + 1) == '-' && (*argv)[argc_count] != NULL)
    			{
    				argc_count++, dst_iter++;
    
    				if (argc_count == argv_size)
    				{
    					argv_size += 5;
    					*argv = realloc(*argv, sizeof(void *) * argv_size);
    				}
    
    				(*argv)[argc_count] = dst_iter;
    			}
    		}
    		else switch(*src_iter)
    		{
    			case '"':
    			case '\'':
    				quote = *src_iter;
    				break;
    
    			case '\\':
    				src_iter++;
    
    				if (!*src_iter)
    				{
    					free(argv);
    					free(buf);
    					return -1;
    				}
    			default:
    				*dst_iter++ = *src_iter;
    				break;
    		}
    
    		src_iter++;
    	}
    
    	if (strlen((*argv)[argc_count])) {
    		argc_count++;
    	}
    
    	*argc = argc_count;
    	return 0;
    }