L4Re/departure

libext2fs/lib/libsupport/argv_parse.c

618:7123a7307a82
8 months ago Paul Boddie Introduced some debugging output control.
     1 /*     2  * argv_parse.c --- utility function for parsing a string into a     3  * 	argc, argv array.     4  *     5  * This file defines a function argv_parse() which parsing a     6  * passed-in string, handling double quotes and backslashes, and     7  * creates an allocated argv vector which can be freed using the     8  * argv_free() function.     9  *    10  * See argv_parse.h for the formal definition of the functions.    11  *    12  * Copyright 1999 by Theodore Ts'o.    13  *    14  * Permission to use, copy, modify, and distribute this software for    15  * any purpose with or without fee is hereby granted, provided that    16  * the above copyright notice and this permission notice appear in all    17  * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE    18  * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,    19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.    20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,    21  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER    22  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION    23  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR    24  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't    25  * it sick that the U.S. culture of lawsuit-happy lawyers requires    26  * this kind of disclaimer?)    27  *    28  * Version 1.1, modified 2/27/1999    29  */    30     31 #include "config.h"    32 #ifdef HAVE_STDLIB_H    33 #include <stdlib.h>    34 #endif    35 #include <ctype.h>    36 #include <string.h>    37 #include "argv_parse.h"    38     39 #define STATE_WHITESPACE	1    40 #define STATE_TOKEN		2    41 #define STATE_QUOTED		3    42     43 /*    44  * Returns 0 on success, -1 on failure.    45  */    46 int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)    47 {    48 	int	argc = 0, max_argc = 0;    49 	char 	**argv, **new_argv, *buf, ch;    50 	char	*cp = 0, *outcp = 0;    51 	int	state = STATE_WHITESPACE;    52     53 	buf = malloc(strlen(in_buf)+1);    54 	if (!buf)    55 		return -1;    56     57 	max_argc = 0; argc = 0; argv = 0;    58 	outcp = buf;    59 	for (cp = in_buf; (ch = *cp); cp++) {    60 		if (state == STATE_WHITESPACE) {    61 			if (isspace((int) ch))    62 				continue;    63 			/* Not whitespace, so start a new token */    64 			state = STATE_TOKEN;    65 			if (argc >= max_argc) {    66 				max_argc += 3;    67 				new_argv = realloc(argv,    68 						  (max_argc+1)*sizeof(char *));    69 				if (!new_argv) {    70 					free(argv);    71 					free(buf);    72 					return -1;    73 				}    74 				argv = new_argv;    75 			}    76 			argv[argc++] = outcp;    77 		}    78 		if (state == STATE_QUOTED) {    79 			if (ch == '"')    80 				state = STATE_TOKEN;    81 			else    82 				*outcp++ = ch;    83 			continue;    84 		}    85 		/* Must be processing characters in a word */    86 		if (isspace((int) ch)) {    87 			/*    88 			 * Terminate the current word and start    89 			 * looking for the beginning of the next word.    90 			 */    91 			*outcp++ = 0;    92 			state = STATE_WHITESPACE;    93 			continue;    94 		}    95 		if (ch == '"') {    96 			state = STATE_QUOTED;    97 			continue;    98 		}    99 		if (ch == '\\') {   100 			ch = *++cp;   101 			switch (ch) {   102 			case '\0':   103 				ch = '\\'; cp--; break;   104 			case 'n':   105 				ch = '\n'; break;   106 			case 't':   107 				ch = '\t'; break;   108 			case 'b':   109 				ch = '\b'; break;   110 			}   111 		}   112 		*outcp++ = ch;   113 	}   114 	if (state != STATE_WHITESPACE)   115 		*outcp++ = '\0';   116 	if (argv == 0) {   117 		argv = malloc(sizeof(char *));   118 		free(buf);   119 	}   120 	argv[argc] = 0;   121 	if (ret_argc)   122 		*ret_argc = argc;   123 	if (ret_argv)   124 		*ret_argv = argv;   125 	return 0;   126 }   127    128 void argv_free(char **argv)   129 {   130 	free(*argv);   131 	free(argv);   132 }   133    134 #ifdef DEBUG   135 /*   136  * For debugging   137  */   138    139 #include <stdio.h>   140    141 int main(int argc, char **argv)   142 {   143 	int	ac, ret;   144 	char	**av, **cpp;   145 	char	buf[256];   146    147 	while (!feof(stdin)) {   148 		if (fgets(buf, sizeof(buf), stdin) == NULL)   149 			break;   150 		ret = argv_parse(buf, &ac, &av);   151 		if (ret != 0) {   152 			printf("Argv_parse returned %d!\n", ret);   153 			continue;   154 		}   155 		printf("Argv_parse returned %d arguments...\n", ac);   156 		for (cpp = av; *cpp; cpp++) {   157 			if (cpp != av)   158 				printf(", ");   159 			printf("'%s'", *cpp);   160 		}   161 		printf("\n");   162 		argv_free(av);   163 	}   164 	exit(0);   165 }   166 #endif /* DEBUG */