//  ------------------------------------------------------------------------
//
//  Copyright (C) 2009-2011 Fons Adriaensen <fons@linuxaudio.org>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//  ------------------------------------------------------------------------


#include <ctype.h>


#define SQUOTE 39 
#define DQUOTE 34
#define BSLASH 92


// See the header file for a description.

int sstring (const char *srce, char *dest, int size)
{
    int i, j;
    unsigned int c, ef, qf;

    if (size < 0) return 0;
    i = j = ef = qf = 0;
    while (true)
    {
	if (j == size)
	{
	    // Non-zero char in last position of dest, return error.
	    dest [0] = 0;
	    return 0;
	}
	c = srce [i++];
	if (iscntrl (c))
	{
	    // Control character. If within quotes or escaped return error,
	    // else terminate scanning.
	    if (qf | ef)
	    {
		dest [0] = 0;
                return 0;
	    }
            dest [j] = 0;
	    return --i;
	}
	if (ef)
	{
	    // Escaped character. If tab, insert space, else
            // insert the character as is. Reset escape flag.
	    if (isblank (c)) c = ' ';
	    dest [j++] = c;
	    ef = 0;
	    continue;
	}
	if (c == BSLASH)
	{
	    // An '\'. If in single quotes, treat as normal
            // character, else set the escape flag.
	    if (qf == SQUOTE) dest [j++] = c;
            else ef = c;
	    continue;
	}
        if ((c == SQUOTE) || (c == DQUOTE))
        {
	    // Single or double quote. If we have a leading quote,
            // terminate scanning if this one matches it, or return
            // error if not. Else set as leading quote.
    	    if (c == qf)
	    {
		dest [j] = 0;
		return i;
	    }
	    if (qf || j)
	    {
		dest [0] = 0;
		return 0;
	    }
            qf = c;
	    continue;
	}
	if (isblank (c))
	{
	    // Space or tab. Skip if leading, insert space if quoted,
            // or otherwise terminate scanning.
	    if (qf)
	    {
		dest [j++] = ' ';
		continue;
	    }
	    if (j)
	    {
		dest [j++] = 0;
		return --i;
	    }
	    continue;
	}
	// Normal character.
	dest [j++] = c;
    }	    
    return 0;
}

