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
16 enum 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
ss_parse(sci_idx,line_ptr,argc_ptr,argv_ptr,quiet)50 int 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 }
147 end_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