/* 
 * execl-cmdline.c
 * 
 * Copyright (c) 2018-2019 Eric Vidal <eric@obarun.org>
 * 
 * All rights reserved.
 * 
 * This file is part of Obarun. It is subject to the license terms in
 * the LICENSE file found in the top-level directory of this
 * distribution.
 * This file may not be copied, modified, propagated, or distributed
 * except according to the terms contained in the LICENSE file./
 */

#include <string.h>

#include <oblibs/string.h>
#include <oblibs/stralist.h>
#include <oblibs/error2.h>

#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/env.h>
#include <skalibs/djbunix.h>
#include <skalibs/sgetopt.h>

#include <execline/execline.h>

#define USAGE "execl-cmdline [ -s ] { command... }"

int clean_val_doublequoted(genalloc *ga,char const *line)
{
	size_t slen = strlen(line) ;
	size_t tl ;
	char s[slen+1] ;
	memcpy(s,line,slen) ;
	s[slen] = 0 ;
	int f = 0, r = 0 , prev = 0 ;
	r = get_len_until(s,'"') ;
	if (r < 0)
	{
		if (!clean_val(ga,s)) return 0 ;
		return 1 ;
	}
	for (int i = 0 ; i < slen ; i++)
	{
		if (s[i] == '"')
		{
			if (f)
			{
				char t[slen+1] ;
				tl = i-1 ;
				memcpy(t,s+prev,tl-prev+1) ;
				t[tl-prev+1] = 0 ;
				if (!stra_add(ga,t)) return 0 ;
				f = 0 ; prev = i+1 ;
			}
			else
			{
				if (i > 0)
				{
					char t[slen+1] ;
					tl = i ;
					if (prev == tl){ f++ ; continue ; }
					memcpy(t,s+prev,tl-prev) ;
					t[tl-prev] = 0 ;
					if (!clean_val(ga,t)) return 0 ;
					f++ ; prev = i+1 ;
				}
				else f++ ; 
			}
		}
		else
		if (i+1 == slen)
		{
			char t[slen+1] ;
			tl = i - 1 ;
			memcpy(t,s+prev,slen-prev) ;
			t[slen-prev] = 0 ;
			if (!clean_val(ga,t)) return 0 ;
			break ;
		}
	}
	if (f) strerr_dief2x(111,"odd number of double quote in: ",line) ;

	return 1 ;
}

int main(int argc, char const **argv, char const *const *envp)
{

	int r, argc1, split ;

	PROG = "execl-cmdline" ;
	
	stralloc tmodifs = STRALLOC_ZERO ;
	stralloc modifs = STRALLOC_ZERO ;
	genalloc ga = GENALLOC_ZERO ;
	
	r =  argc1 = split = 0 ;
	
	{
		subgetopt_t l = SUBGETOPT_ZERO ;
		for (;;)
		{
		  int opt = subgetopt_r(argc, argv, "s", &l) ;
		  if (opt == -1) break ;
		  switch (opt)
		  {
			case 's' : split = 1 ; break ;
			default : exitusage(USAGE) ;
		  }
		}
		argc -= l.ind ; argv += l.ind ;
	}
	argc1 = el_semicolon(argv) ;
	if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
	argv[argc1] = 0 ;
	
	char const **newargv = argv ;
	for (int i = 0; i < argc1 ; i++, newargv++)
	{	
		if (!*newargv[0])
			continue ;
		
		if (!stralloc_cats(&tmodifs,*newargv)) retstralloc(111,"tmodifs") ;
		if (split)
		{
			if (!stralloc_cats(&tmodifs," ")) retstralloc(111,"tmodifs") ;
		}
		else if (!stralloc_0(&tmodifs)) retstralloc(111,"tmodifs_0") ;
		r++;
	}
	
	if (split)
	{
		if (!clean_val_doublequoted(&ga,tmodifs.s)) strerr_diefu2x(111,"clean val: ",tmodifs.s) ;
		for (unsigned int i = 0 ; i < genalloc_len(stralist,&ga) ; i++)
		{
			stralloc_cats(&modifs,gaistr(&ga,i)) ;
			stralloc_0(&modifs) ;
		}
		r = genalloc_len(stralist,&ga) ;
		genalloc_deepfree(stralist,&ga,stra_free) ;
	}
	else if (!stralloc_copy(&modifs,&tmodifs)) retstralloc(111,"copy") ;
	
	stralloc_free(&tmodifs) ;
	
	char const *newarg[r + 1] ;
    if (!env_make(newarg, r, modifs.s, modifs.len)) strerr_diefu1sys(111, "env_make") ;
    newarg[r] = 0 ;

	xpathexec_run(newarg[0],newarg,envp) ;
}