/* argcv.c - simple functions for parsing input based on whitespace Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "argcv.h" /* * takes a string and splits it into several strings, breaking at ' ' * command is the string to split * the number of strings is placed into argc * the split strings are put into argv * returns 0 on success, nonzero on failure */ #define isws(c) ((c)==' '||(c)=='\t') #define isdelim(c,delim) ((c)=='"'||strchr(delim,(c))!=NULL) static int argcv_scan (int len, const char *command, const char *delim, int *start, int *end, int *save) { int i = *save; /* Skip initial whitespace */ while (i < len && isws (command[i])) i++; *start = i; switch (command[i]) { case '"': case '\'': while (++i < len && command[i] != command[*start]) ; if (i < len) /* found matching quote */ break; /*FALLTHRU*/ default: if (isdelim (command [i], delim)) break; /* Skip until next whitespace character or end of line */ while (++i < len && !(isws (command [i]) || isdelim (command [i], delim))) ; i--; break; } *end = i; *save = i+1; return *save; } int argcv_get (const char *command, const char *delim, int *argc, char ***argv) { int len = strlen (command); int i = 0; int start, end, save; *argc = 0; *argv = NULL; while (len > 0 && isspace (command[len-1])) len--; if (len < 1) return 1; /* Count number of arguments */ *argc = 1; save = 0; while (argcv_scan (len, command, delim, &start, &end, &save) < len) (*argc)++; *argv = calloc ((*argc + 1), sizeof (char *)); if (*argv == NULL) { return 1; } save = 0; for (i = 0; i < *argc; i++) { int n; argcv_scan (len, command, delim, &start, &end, &save); if (command[start] == '"' && command[end] == '"') { start++; end--; } else if (command[start] == '\'' && command[end] == '\'') { start++; end--; } n = end - start + 1; (*argv)[i] = calloc (n+1, sizeof (char)); if ((*argv)[i] == NULL) return 1; memcpy ((*argv)[i], &command[start], n); (*argv)[i][n] = 0; } (*argv)[i] = NULL; return 0; } /* * frees all elements of an argv array * argc is the number of elements * argv is the array */ int argcv_free (int argc, char **argv) { while (--argc >= 0) if (argv[argc]) free (argv[argc]); free (argv); return 1; } /* Take a argv an make string separated by ' '. */ int argcv_string (int argc, char **argv, char **pstring) { int i; size_t len; char *buffer; /* No need. */ if (pstring == NULL) return 1; buffer = malloc (1); if (buffer == NULL) return 1; *buffer = '\0'; for (len = i = 0; i < argc; i++) { char *newbuf = NULL; len += strlen (argv[i]) + 2; newbuf = realloc (buffer, len); if (newbuf == NULL) { free(buffer); return 1; } buffer = newbuf; if (i != 0) snprintf (buffer + strlen(buffer), len - strlen(buffer), "%s", " "); snprintf (buffer + strlen(buffer), len - strlen(buffer), "%s", argv[i]); } /* Strip off trailing space. */ if (*buffer != '\0') { while (buffer[strlen (buffer) - 1] == ' ') { buffer[strlen (buffer) - 1] = '\0'; } } if (pstring) *pstring = buffer; return 0; } #if 0 char *command = "set prompt=\"& \""; main() { int i, argc; char **argv; argcv_get (command, "=", &argc, &argv); printf ("%d args:\n", argc); for (i = 0; i < argc; i++) printf ("%s\n", argv[i]); } #endif