1251881Speter/*
2251881Speter * $Id: argv.c,v 1.2 2012/11/30 20:28:23 tom Exp $
3251881Speter *
4251881Speter *  argv - Reusable functions for argv-parsing.
5251881Speter *
6251881Speter *  Copyright 2011,2012	Thomas E. Dickey
7251881Speter *
8251881Speter *  This program is free software; you can redistribute it and/or modify
9251881Speter *  it under the terms of the GNU Lesser General Public License, version 2.1
10251881Speter *  as published by the Free Software Foundation.
11251881Speter *
12251881Speter *  This program is distributed in the hope that it will be useful, but
13251881Speter *  WITHOUT ANY WARRANTY; without even the implied warranty of
14251881Speter *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15251881Speter *  Lesser General Public License for more details.
16251881Speter *
17251881Speter *  You should have received a copy of the GNU Lesser General Public
18251881Speter *  License along with this program; if not, write to
19251881Speter *	Free Software Foundation, Inc.
20251881Speter *	51 Franklin St., Fifth Floor
21251881Speter *	Boston, MA 02110, USA.
22251881Speter */
23251881Speter
24251881Speter#include <dialog.h>
25251881Speter#include <string.h>
26251881Speter
27251881Speter/*
28251881Speter * Convert a string to an argv[], returning a char** index (which must be
29251881Speter * freed by the caller).  The string is modified (replacing gaps between
30251881Speter * tokens with nulls).
31251881Speter */
32251881Speterchar **
33251881Speterdlg_string_to_argv(char *blob)
34251881Speter{
35251881Speter    size_t n;
36251881Speter    int pass;
37251881Speter    size_t length = strlen(blob);
38251881Speter    char **result = 0;
39251881Speter
40251881Speter    for (pass = 0; pass < 2; ++pass) {
41251881Speter	bool inparm = FALSE;
42251881Speter	bool quoted = FALSE;
43251881Speter	char *param = blob;
44251881Speter	size_t count = 0;
45251881Speter
46251881Speter	for (n = 0; n < length; ++n) {
47251881Speter	    if (quoted && blob[n] == '"') {
48251881Speter		quoted = FALSE;
49251881Speter	    } else if (blob[n] == '"') {
50251881Speter		quoted = TRUE;
51251881Speter		if (!inparm) {
52251881Speter		    if (pass)
53251881Speter			result[count] = param;
54251881Speter		    ++count;
55251881Speter		    inparm = TRUE;
56251881Speter		}
57251881Speter	    } else if (blob[n] == '\\') {
58251881Speter		if (quoted && !isspace(UCH(blob[n + 1]))) {
59251881Speter		    if (pass) {
60251881Speter			*param++ = blob[n];
61251881Speter			*param++ = blob[n + 1];
62251881Speter		    }
63251881Speter		}
64251881Speter		++n;
65251881Speter	    } else if (!quoted && isspace(UCH(blob[n]))) {
66251881Speter		inparm = FALSE;
67251881Speter		if (pass) {
68251881Speter		    *param++ = '\0';
69251881Speter		}
70251881Speter	    } else {
71251881Speter		if (!inparm) {
72251881Speter		    if (pass)
73251881Speter			result[count] = param;
74251881Speter		    ++count;
75251881Speter		    inparm = TRUE;
76251881Speter		}
77251881Speter		if (pass) {
78251881Speter		    *param++ = blob[n];
79251881Speter		}
80251881Speter	    }
81251881Speter	}
82251881Speter
83251881Speter	if (!pass) {
84251881Speter	    if (count) {
85251881Speter		result = dlg_calloc(char *, count + 1);
86251881Speter		assert_ptr(result, "string_to_argv");
87251881Speter	    } else {
88251881Speter		break;		/* no tokens found */
89251881Speter	    }
90251881Speter	} else {
91251881Speter	    *param = '\0';
92251881Speter	}
93251881Speter    }
94251881Speter    return result;
95251881Speter}
96251881Speter
97251881Speter/*
98251881Speter * Count the entries in an argv list.
99251881Speter */
100251881Speterint
101251881Speterdlg_count_argv(char **argv)
102251881Speter{
103251881Speter    int result = 0;
104251881Speter
105251881Speter    if (argv != 0) {
106251881Speter	while (argv[result] != 0)
107251881Speter	    ++result;
108251881Speter    }
109251881Speter    return result;
110251881Speter}
111251881Speter
112251881Speterint
113251881Speterdlg_eat_argv(int *argcp, char ***argvp, int start, int count)
114251881Speter{
115251881Speter    int k;
116251881Speter
117251881Speter    *argcp -= count;
118251881Speter    for (k = start; k <= *argcp; k++)
119251881Speter	(*argvp)[k] = (*argvp)[k + count];
120251881Speter    (*argvp)[*argcp] = 0;
121251881Speter    return TRUE;
122251881Speter}
123251881Speter