1/* 2 * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation on the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28/* 29 * Authors: 30 * Rickard E. (Rik) Faith <faith@redhat.com> 31 * 32 */ 33 34/** \file 35 * Generic comma-delimited argument processing. */ 36 37#ifdef HAVE_DMX_CONFIG_H 38#include <dmx-config.h> 39#endif 40 41#define DMX_ARG_TEST 0 42 43#include "dmx.h" 44#include "dmxarg.h" 45#include <stdio.h> 46#include <string.h> 47 48#if DMX_ARG_TEST 49#include <stdlib.h> 50#endif 51 52/** Stores the parsed argument list. */ 53struct _dmxArg { 54 int argc; /**< Number of arguments in argv */ 55 int argm; /**< Maximum number of arguments store-able in argv */ 56 const char **argv; /**< Arguments */ 57}; 58 59/** Create an (externally opaque) \a dmxArg object. */ 60dmxArg dmxArgCreate(void) 61{ 62 dmxArg a = malloc(sizeof(*a)); 63 a->argc = 0; 64 a->argm = 2; 65 a->argv = malloc(a->argm * sizeof(*a->argv)); 66 a->argv[0] = NULL; 67 return a; 68} 69 70/** Free the specified \a dmxArg object. */ 71void dmxArgFree(dmxArg a) 72{ 73 int i; 74 75 for (i = 0; i < a->argc; i++) free((char *)a->argv[i]); 76 free(a->argv); 77 free(a); 78} 79 80/** Add the \a string as the next argument in the \a dmxArg object. */ 81void dmxArgAdd(dmxArg a, const char *string) 82{ 83 if (a->argm <= a->argc + 2) 84 a->argv = realloc(a->argv, sizeof(*a->argv) * (a->argm *= 2)); 85 a->argv[a->argc++] = strdup(string); 86 a->argv[a->argc] = NULL; 87} 88 89/** Return the argument number \a item in the \a dmxArg object. 90 * Arguments are 0 based. NULL will be returned for values less than 0 91 * or equal to or greater than the number of arguments in the object. */ 92const char *dmxArgV(dmxArg a, int item) 93{ 94 if (item < 0 || item >= a->argc) return NULL; 95 return a->argv[item]; 96} 97 98/** Return the number of arguments in the \a dmxArg object. */ 99int dmxArgC(dmxArg a) 100{ 101 return a->argc; 102} 103 104/** Parse a string into arguments delimited by commas. Return a new \a 105 * dmxArg object containing the arguments. */ 106dmxArg dmxArgParse(const char *string) 107{ 108 char *tmp; 109 char *start, *pt; 110 dmxArg a = dmxArgCreate(); 111 int done; 112 int len; 113 114 if (!string) return a; 115 116 len = strlen(string) + 2; 117 tmp = malloc(len); 118 strncpy(tmp, string, len); 119 120 for (start = pt = tmp, done = 0; !done && *pt; start = ++pt) { 121 for (;*pt && *pt != ','; pt++); 122 if (!*pt) done = 1; 123 *pt = '\0'; 124 dmxArgAdd(a, start); 125 } 126 if (!done) dmxArgAdd(a, ""); /* Final comma */ 127 128 free(tmp); 129 return a; 130} 131 132#if DMX_ARG_TEST 133static void dmxArgPrint(dmxArg a) 134{ 135 int i; 136 137 printf(" argc = %d\n", dmxArgC(a)); 138 for (i = 0; i < dmxArgC(a); i++) 139 printf(" argv[%d] = \"%s\"\n", i, dmxArgV(a, i)); 140} 141 142static void dmxArgTest(const char *string) 143{ 144 dmxArg a; 145 146 if (!string) 147 printf("Testing NULL\n"); 148 else if (!strlen(string)) 149 printf("Testing (empty)\n"); 150 else 151 printf("Testing \"%s\"\n", string); 152 153 a = dmxArgParse(string); 154 dmxArgPrint(a); 155 dmxArgFree(a); 156} 157 158int main(void) 159{ 160 dmxArgTest(NULL); 161 dmxArgTest(""); 162 dmxArgTest(","); 163 164 dmxArgTest("a"); 165 dmxArgTest("a,"); 166 dmxArgTest(",a"); 167 168 dmxArgTest("a,b"); 169 dmxArgTest("a,b,"); 170 dmxArgTest("a,b,,"); 171 dmxArgTest("a,b,,c"); 172 173 return 0; 174} 175#endif 176