xref: /illumos-gate/usr/src/lib/krb5/ss/parse.c (revision 56a424cca6b3f91f31bdab72a4626c48c779fe8b)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 
3 /*
4  * Copyright 1987, 1988 by MIT Student Information Processing Board
5  *
6  * For copyright info, see copyright.h.
7  */
8 
9 #include "ss_internal.h"
10 #include "copyright.h"
11 #include <errno.h>
12 
13 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
14 
15 /*
16  * parse(line_ptr, argc_ptr)
17  *
18  * Function:
19  *      Parses line, dividing at whitespace, into tokens, returns
20  *      the "argc" and "argv" values.
21  * Arguments:
22  *      line_ptr (char *)
23  *              Pointer to text string to be parsed.
24  *      argc_ptr (int *)
25  *              Where to put the "argc" (number of tokens) value.
26  * Returns:
27  *      argv (char **)
28  *              Series of pointers to parsed tokens.
29  */
30 
31 #define NEW_ARGV(old,n) (char **)realloc((char *)old,\
32 					 (unsigned)(n+2)*sizeof(char*))
33 
34 char **ss_parse (sci_idx, line_ptr, argc_ptr)
35     int sci_idx;
36     register char *line_ptr;
37     int *argc_ptr;
38 {
39     register char **argv, *cp;
40     register int argc;
41     register enum parse_mode parse_mode;
42 
43     argv = (char **) malloc (sizeof(char *));
44     if (argv == (char **)NULL) {
45 	ss_error(sci_idx, errno, "Can't allocate storage");
46 	*argc_ptr = 0;
47 	return(argv);
48     }
49     *argv = (char *)NULL;
50 
51     argc = 0;
52 
53     parse_mode = WHITESPACE;	/* flushing whitespace */
54     cp = line_ptr;		/* cp is for output */
55     while (1) {
56 #ifdef DEBUG
57 	{
58 	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
59 	}
60 #endif
61 	while (parse_mode == WHITESPACE) {
62 	    if (*line_ptr == '\0')
63 		goto end_of_line;
64 	    if (*line_ptr == ' ' || *line_ptr == '\t') {
65 		line_ptr++;
66 		continue;
67 	    }
68 	    if (*line_ptr == '"') {
69 		/* go to quoted-string mode */
70 		parse_mode = QUOTED_STRING;
71 		cp = line_ptr++;
72 		argv = NEW_ARGV (argv, argc);
73 		argv[argc++] = cp;
74 		argv[argc] = NULL;
75 	    }
76 	    else {
77 		/* random-token mode */
78 		parse_mode = TOKEN;
79 		cp = line_ptr;
80 		argv = NEW_ARGV (argv, argc);
81 		argv[argc++] = line_ptr;
82 		argv[argc] = NULL;
83 	    }
84 	}
85 	while (parse_mode == TOKEN) {
86 	    if (*line_ptr == '\0') {
87 		*cp++ = '\0';
88 		goto end_of_line;
89 	    }
90 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
91 		*cp++ = '\0';
92 		line_ptr++;
93 		parse_mode = WHITESPACE;
94 	    }
95 	    else if (*line_ptr == '"') {
96 		line_ptr++;
97 		parse_mode = QUOTED_STRING;
98 	    }
99 	    else {
100 		*cp++ = *line_ptr++;
101 	    }
102 	}
103 	while (parse_mode == QUOTED_STRING) {
104 	    if (*line_ptr == '\0') {
105 		ss_error (sci_idx, 0,
106 			  "Unbalanced quotes in command line");
107 		free (argv);
108 		*argc_ptr = 0;
109 		return NULL;
110 	    }
111 	    else if (*line_ptr == '"') {
112 		if (*++line_ptr == '"') {
113 		    *cp++ = '"';
114 		    line_ptr++;
115 		}
116 		else {
117 		    parse_mode = TOKEN;
118 		}
119 	    }
120 	    else {
121 		*cp++ = *line_ptr++;
122 	    }
123 	}
124     }
125 end_of_line:
126     *argc_ptr = argc;
127 #ifdef DEBUG
128     {
129 	int i;
130 	printf ("argc = %d\n", argc);
131 	for (i = 0; i <= argc; i++)
132 	    printf ("\targv[%2d] = `%s'\n", i,
133 		    argv[i] ? argv[i] : "<NULL>");
134     }
135 #endif
136     return(argv);
137 }
138