1 /* 2 * $Id: argv.c,v 1.5 2015/05/13 00:34:39 tom Exp $ 3 * 4 * argv - Reusable functions for argv-parsing. 5 * 6 * Copyright 2011-2014,2015 Thomas E. Dickey 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License, version 2.1 10 * as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this program; if not, write to 19 * Free Software Foundation, Inc. 20 * 51 Franklin St., Fifth Floor 21 * Boston, MA 02110, USA. 22 */ 23 24 #include <dialog.h> 25 #include <string.h> 26 27 /* 28 * Convert a string to an argv[], returning a char** index (which must be 29 * freed by the caller). The string is modified (replacing gaps between 30 * tokens with nulls). 31 */ 32 char ** 33 dlg_string_to_argv(char *blob) 34 { 35 size_t n; 36 int pass; 37 size_t length = strlen(blob); 38 char **result = 0; 39 40 DLG_TRACE(("# dlg_string_to_argv:\n#\t%s\n", blob)); 41 for (pass = 0; pass < 2; ++pass) { 42 bool inparm = FALSE; 43 bool quoted = FALSE; 44 char *param = blob; 45 size_t count = 0; 46 47 for (n = 0; n < length; ++n) { 48 if (quoted && blob[n] == '"') { 49 quoted = FALSE; 50 } else if (blob[n] == '"') { 51 quoted = TRUE; 52 if (!inparm) { 53 if (pass) 54 result[count] = param; 55 ++count; 56 inparm = TRUE; 57 } 58 } else if (!quoted && isspace(UCH(blob[n]))) { 59 if (inparm) { 60 if (pass) { 61 *param++ = '\0'; 62 } 63 inparm = FALSE; 64 } 65 } else { 66 if (!inparm) { 67 if (pass) 68 result[count] = param; 69 ++count; 70 inparm = TRUE; 71 } 72 if (blob[n] == '\\') { 73 if (++n == length) 74 break; /* The string is terminated by a backslash */ 75 } 76 if (pass) { 77 *param++ = blob[n]; 78 } 79 } 80 } 81 82 if (!pass) { 83 if (count) { 84 result = dlg_calloc(char *, count + 1); 85 assert_ptr(result, "string_to_argv"); 86 } else { 87 break; /* no tokens found */ 88 } 89 } else { 90 *param = '\0'; 91 } 92 } 93 #ifdef HAVE_DLG_TRACE 94 if (result != 0) { 95 for (n = 0; result[n] != 0; ++n) { 96 DLG_TRACE(("#\targv[%d] = %s\n", (int) n, result[n])); 97 } 98 } 99 #endif 100 return result; 101 } 102 103 /* 104 * Count the entries in an argv list. 105 */ 106 int 107 dlg_count_argv(char **argv) 108 { 109 int result = 0; 110 111 if (argv != 0) { 112 while (argv[result] != 0) 113 ++result; 114 } 115 return result; 116 } 117 118 int 119 dlg_eat_argv(int *argcp, char ***argvp, int start, int count) 120 { 121 int k; 122 123 *argcp -= count; 124 for (k = start; k <= *argcp; k++) 125 (*argvp)[k] = (*argvp)[k + count]; 126 (*argvp)[*argcp] = 0; 127 return TRUE; 128 } 129