xref: /illumos-gate/usr/src/cmd/lp/lib/lp/getlist.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.13	*/
27 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
28 
29 #include "string.h"
30 #include "errno.h"
31 #include "stdlib.h"
32 
33 #include "lp.h"
34 
35 #if	defined(__STDC__)
36 static char		*unq_strdup ( char * , char * );
37 #else
38 static char		*unq_strdup();
39 #endif
40 
41 /**
42  ** getlist() - CONSTRUCT LIST FROM STRING
43  **/
44 
45 /*
46  * Any number of characters from "ws", or a single
47  * character from "hardsep", can separate items in the list.
48  */
49 
50 char **
51 #if	defined(__STDC__)
52 getlist (
53 	char *			str,
54 	char *			ws,
55 	char *			hardsep
56 )
57 #else
58 getlist (str, ws, hardsep)
59 	register char		*str,
60 				*ws;
61 	char			*hardsep;
62 #endif
63 {
64 	register char		**list,
65 				*p,
66 				*sep,
67 				c;
68 
69 	int			n,
70 				len;
71 
72 	char			buf[10];
73 
74 
75 	if (!str || !*str)
76 		return (0);
77 
78 	/*
79 	 * Construct in "sep" the full list of characters that
80 	 * can separate items in the list. Avoid a "malloc()"
81 	 * if possible.
82 	 */
83 	len = strlen(ws) + strlen(hardsep) + 1;
84 	if (len > sizeof(buf)) {
85 		if (!(sep = Malloc(len))) {
86 			errno = ENOMEM;
87 			return (0);
88 		}
89 	} else
90 		sep = buf;
91 	strcpy (sep, hardsep);
92 	strcat (sep, ws);
93 
94 	/*
95 	 * Skip leading white-space.
96 	 */
97 	str += strspn(str, ws);
98 	if (!*str)
99 		return (0);
100 
101 	/*
102 	 * Strip trailing white-space.
103 	 */
104 	p = strchr(str, '\0');
105 	while (--p != str && strchr(ws, *p))
106 		;
107 	*++p = 0;
108 
109 	/*
110 	 * Pass 1: Count the number of items in the list.
111 	 */
112 	for (n = 0, p = str; *p; ) {
113 		if ((c = *p++) == '\\')
114 			p++;
115 		else
116 			if (strchr(sep, c)) {
117 				n++;
118 				p += strspn(p, ws);
119 				if (
120 					!strchr(hardsep, c)
121 				     && strchr(hardsep, *p)
122 				) {
123 					p++;
124 					p += strspn(p, ws);
125 				}
126 			}
127 	}
128 
129 	/*
130 	 * Pass 2: Create the list.
131 	 */
132 
133 	/*
134 	 * Pass 1 counted the number of list separaters, so
135 	 * add 2 to the count (includes 1 for terminating null).
136 	 */
137 	if (!(list = (char **)Malloc((n+2) * sizeof(char *)))) {
138 		errno = ENOMEM;
139 		goto Done;
140 	}
141 
142 	/*
143 	 * This loop will copy all but the last item.
144 	 */
145 	for (n = 0, p = str; *p; )
146 		if ((c = *p++) == '\\')
147 			p++;
148 		else
149 			if (strchr(sep, c)) {
150 
151 				p[-1] = 0;
152 				list[n++] = unq_strdup(str, sep);
153 				p[-1] = c;
154 
155 				p += strspn(p, ws);
156 				if (
157 					!strchr(hardsep, c)
158 				     && strchr(hardsep, *p)
159 				) {
160 					p++;
161 					p += strspn(p, ws);
162 				}
163 				str = p;
164 
165 			}
166 
167 	list[n++] = unq_strdup(str, sep);
168 
169 	list[n] = 0;
170 
171 Done:	if (sep != buf)
172 		Free (sep);
173 	return (list);
174 }
175 
176 /**
177  ** unq_strdup()
178  **/
179 
180 static char *
181 #if	defined(__STDC__)
182 unq_strdup (
183 	char *			str,
184 	char *			sep
185 )
186 #else
187 unq_strdup (str, sep)
188 	char			*str,
189 				*sep;
190 #endif
191 {
192 	register int		len	= 0;
193 
194 	register char		*p,
195 				*q,
196 				*ret;
197 
198 
199 	for (p = str; *p; p++)
200 		if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
201 			len++;
202 	if (!(q = ret = Malloc(len + 1)))
203 		return (0);
204 	for (p = str; *p; p++)
205 		if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
206 			*q++ = *p;
207 	*q = 0;
208 	return (ret);
209 }
210