1/* 2 * Copyright 1987, 1988 by MIT Student Information Processing Board 3 * 4 * For copyright info, see copyright.h. 5 */ 6 7/* 8 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 9 * Use is subject to license terms. 10 */ 11 12#include "ss_internal.h" 13#include "copyright.h" 14#include <errno.h> 15 16enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING }; 17 18 19/* 20 * Solaris Kerberos: 21 * ss_parse has been modified slightly from the original in two ways. 22 * 1) A new parameter "quiet" has been added which is used to silence 23 * error or warning messages. 24 * 2) ss_parse now returns an error status instead of argv - this is to 25 * allow an error to be distinguished from no tokens when parsing an empty 26 * string. 27 * Both of these changes allow ss_parse to be used during tab-completion. 28 */ 29 30/* 31 * parse(line_ptr, argc_ptr) 32 * 33 * Function: 34 * Parses line, dividing at whitespace, into tokens, returns 35 * the "argc" and "argv" values. 36 * Arguments: 37 * line_ptr (char *) 38 * Pointer to text string to be parsed. 39 * argc_ptr (int *) 40 * Where to put the "argc" (number of tokens) value. 41 * argv_ptr (char ***) 42 * Where to put the series of pointers to parsed tokens. 43 * Returns: 44 * error (0 - success, non-zero on failure) 45 */ 46 47#define NEW_ARGV(old,n) (char **)realloc((char *)old,\ 48 (unsigned)(n+2)*sizeof(char*)) 49 50int ss_parse (sci_idx, line_ptr, argc_ptr, argv_ptr, quiet) 51 int sci_idx; 52 register char *line_ptr; 53 int *argc_ptr; 54 char ***argv_ptr; 55 int quiet; 56{ 57 register char **argv, *cp; 58 register int argc; 59 register enum parse_mode parse_mode; 60 61 argv = (char **) malloc (sizeof(char *)); 62 if (argv == (char **)NULL) { 63 if (!quiet) 64 ss_error(sci_idx, errno, "Can't allocate storage"); 65 *argc_ptr = 0; 66 *argv_ptr = argv; 67 return(ENOMEM); 68 } 69 *argv = (char *)NULL; 70 71 argc = 0; 72 73 parse_mode = WHITESPACE; /* flushing whitespace */ 74 cp = line_ptr; /* cp is for output */ 75 while (1) { 76#ifdef DEBUG 77 { 78 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 79 } 80#endif 81 while (parse_mode == WHITESPACE) { 82 if (*line_ptr == '\0') 83 goto end_of_line; 84 if (*line_ptr == ' ' || *line_ptr == '\t') { 85 line_ptr++; 86 continue; 87 } 88 if (*line_ptr == '"') { 89 /* go to quoted-string mode */ 90 parse_mode = QUOTED_STRING; 91 cp = line_ptr++; 92 argv = NEW_ARGV (argv, argc); 93 argv[argc++] = cp; 94 argv[argc] = NULL; 95 } 96 else { 97 /* random-token mode */ 98 parse_mode = TOKEN; 99 cp = line_ptr; 100 argv = NEW_ARGV (argv, argc); 101 argv[argc++] = line_ptr; 102 argv[argc] = NULL; 103 } 104 } 105 while (parse_mode == TOKEN) { 106 if (*line_ptr == '\0') { 107 *cp++ = '\0'; 108 goto end_of_line; 109 } 110 else if (*line_ptr == ' ' || *line_ptr == '\t') { 111 *cp++ = '\0'; 112 line_ptr++; 113 parse_mode = WHITESPACE; 114 } 115 else if (*line_ptr == '"') { 116 line_ptr++; 117 parse_mode = QUOTED_STRING; 118 } 119 else { 120 *cp++ = *line_ptr++; 121 } 122 } 123 while (parse_mode == QUOTED_STRING) { 124 if (*line_ptr == '\0') { 125 if (!quiet) 126 ss_error (sci_idx, 0, 127 "Unbalanced quotes in command line"); 128 free (argv); 129 *argc_ptr = 0; 130 *argv_ptr = NULL; 131 return (-1); 132 } 133 else if (*line_ptr == '"') { 134 if (*++line_ptr == '"') { 135 *cp++ = '"'; 136 line_ptr++; 137 } 138 else { 139 parse_mode = TOKEN; 140 } 141 } 142 else { 143 *cp++ = *line_ptr++; 144 } 145 } 146 } 147end_of_line: 148 *argc_ptr = argc; 149#ifdef DEBUG 150 { 151 int i; 152 printf ("argc = %d\n", argc); 153 for (i = 0; i <= argc; i++) 154 printf ("\targv[%2d] = `%s'\n", i, 155 argv[i] ? argv[i] : "<NULL>"); 156 } 157#endif 158 *argv_ptr = argv; 159 return(0); 160} 161