xref: /illumos-gate/usr/src/lib/libshare/common/parser.c (revision d656abb5804319b33c85955a73ee450ef7ff9739)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <ctype.h>
29 
30 #define	TK_INIT		0
31 #define	TK_TOKEN	1
32 #define	TK_SKIPWHITE	2
33 #define	TK_QUOTED	3
34 
35 /*
36  * assumes quoted strings are delimited by white space (i.e sp
37  * "string" sp). Backslash can be used to quote a quote mark.
38  * quoted strings will have the quotes stripped.
39  */
40 
41 char *
42 _sa_get_token(char *string)
43 {
44 	static char *orig = NULL;
45 	static char *curp;
46 	char *ret;
47 	int state = TK_INIT;
48 	int c;
49 	int quotechar;
50 
51 	if (string != orig || string == NULL) {
52 		orig = string;
53 		curp = string;
54 		if (string == NULL) {
55 			return (NULL);
56 		}
57 	}
58 	ret = curp;
59 	while ((c = *curp) != '\0') {
60 		switch (state) {
61 		case TK_SKIPWHITE:
62 		case TK_INIT:
63 			if (isspace(c)) {
64 				while (*curp && isspace(*curp))
65 					curp++;
66 				ret = curp;
67 			}
68 			if (c == '"' || c == '\'') {
69 				state = TK_QUOTED;
70 				curp++;
71 				ret = curp;
72 				quotechar = c; /* want to match for close */
73 			} else {
74 				state = TK_TOKEN;
75 			}
76 			break;
77 		case TK_TOKEN:
78 			switch (c) {
79 			case '\\':
80 				curp++;
81 				if (*curp) {
82 					curp++;
83 					break;
84 				} else {
85 					return (ret);
86 				}
87 				break;
88 			default:
89 				if (*curp == '\0' || isspace(c)) {
90 					*curp++ = '\0';
91 					return (ret);
92 				}
93 				curp++;
94 				break;
95 			}
96 			break;
97 		case TK_QUOTED:
98 			switch (c) {
99 			case '\\':
100 				curp++;
101 				if (*curp) {
102 					curp++;
103 					break;
104 				}
105 				curp++;
106 				break;
107 			default:
108 				if (c == '\0' || c == quotechar) {
109 					*curp++ = '\0';
110 					return (ret);
111 				}
112 				curp++;
113 				break;
114 			}
115 			break;
116 		}
117 	}
118 	return (NULL);
119 }
120