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
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.
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]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
32 /* we need to define this to get strtok_r from string.h */
33 /* SEEMS LIKE A BUG TO ME */
46 #include <sys/types.h>
52 static boolean_t
spec_match(spec_t
* spec_p
, char *str
);
61 * spec() - builds a spec
71 queue_init(&new_p
->qn
);
74 new_p
->regexp_p
= NULL
;
76 if (type
== SPEC_REGEXP
) {
77 new_p
->regexp_p
= compile(str_p
, NULL
, NULL
);
78 if (!new_p
->regexp_p
) {
79 semantic_err(gettext("invalid regular expression"));
90 * spec_dup() - duplicates a spec, NOT A SPEC LIST!
94 spec_dup(spec_t
* spec_p
)
98 new_p
= spec(strdup(spec_p
->str
), spec_p
->type
);
106 * spec_destroy() - destroys a spec list
110 spec_destroy(spec_t
* list_p
)
114 while ((spec_p
= (spec_t
*) queue_next(&list_p
->qn
, &list_p
->qn
))) {
115 (void) queue_remove(&spec_p
->qn
);
119 if (spec_p
->regexp_p
)
120 free(spec_p
->regexp_p
);
126 if (list_p
->regexp_p
)
127 free(list_p
->regexp_p
);
130 } /* end spec_destroy */
134 * spec_list() - append a spec_t to a list
138 spec_list(spec_t
* h
,
141 /* queue append handles the NULL cases OK */
142 return ((spec_t
*) queue_append(&h
->qn
, &f
->qn
));
144 } /* end spec_list */
148 * spec_print() - pretty prints a speclist
152 spec_print(FILE * stream
,
155 spec_t
*spec_p
= NULL
;
157 while ((spec_p
= (spec_t
*) queue_next(&list_p
->qn
, &spec_p
->qn
))) {
158 switch (spec_p
->type
) {
160 (void) fprintf(stream
, "'%s'", spec_p
->str
);
163 (void) fprintf(stream
, "/%s/", spec_p
->str
);
168 } /* end spec_print */
172 * spec_match() - called with a spec and a string, returns whether they
177 spec_match(spec_t
* spec_p
,
183 switch (spec_p
->type
) {
185 return ((strcmp(spec_p
->str
, str
) == 0));
188 return ((step(str
, spec_p
->regexp_p
) != NULL
));
193 } /* end spec_match */
197 * spec_attrtrav() - traverse an attribute list, calling the supplied
198 * function on each matching attribute.
202 spec_attrtrav(spec_t
* spec_p
,
212 boolean_t inquote
= B_FALSE
;
215 * * STRATEGY - we make two copies of the attr string. In one *
216 * string we escape (translate) all relevant quoted characters to * a
217 * non-significant character. We use this string to feed to * strtok
218 * to do the parsing. * Once strtok has parsed the string, we use the
219 * same fragement * positions from the unescaped string to pass to
223 /* make two copies of the string */
224 refptr
= strdup(attrs
);
225 escptr
= strdup(attrs
);
227 /* escape any quoted ';'s in the escptr string */
228 for (s
= escptr
; *s
; s
++) {
236 inquote
= (inquote
) ? B_FALSE
: B_TRUE
;
240 /* nothing on purpose */
245 /* loop over each attribute section separated by ';' */
246 for (pair
= strtok_r(escptr
, ";", &lasts
); pair
;
247 pair
= strtok_r(NULL
, ";", &lasts
)) {
254 escattr
= strtok_r(pair
, " \t", &escvals
);
257 * setup the ref pointers to the same locations as the esc
261 * null the reference string in the same spots as the esc
264 refattr
= (refptr
+ (escattr
- escptr
));
265 refattr
[strlen(escattr
)] = '\0';
267 if (escvals
&& *escvals
) {
268 refvals
= (refptr
+ (escvals
- escptr
));
269 refvals
[strlen(escvals
)] = '\0';
275 if (spec_match(spec_p
, refattr
)) {
277 (*fun
) (spec_p
, refattr
, refvals
, calldatap
);
279 (*fun
) (spec_p
, refattr
, emptystr
, calldatap
);
289 } /* end spec_attrtrav */
293 * spec_valtrav() - traverse an value list, calling the supplied function on
294 * each matching value.
298 spec_valtrav(spec_t
* spec_p
,
305 boolean_t intoken
= B_FALSE
;
306 boolean_t inquote
= B_FALSE
;
308 /* return immeadiatly on null pointers */
312 /* special case, match once on empty string */
314 if (spec_match(spec_p
, valstr
))
315 (*fun
) (spec_p
, valstr
, calldatap
);
318 for (s
= s0
= valstr
; ; s
++) {
322 if (spec_match(spec_p
, s0
))
323 (*fun
) (spec_p
, s0
, calldatap
);
325 return; /* ALL DONE */
329 /* end a quoted string */
333 if (spec_match(spec_p
, s0
))
334 (*fun
) (spec_p
, s0
, calldatap
);
335 /* next string starts past the quote */
338 /* start a quoted string */
341 s0
= s
+ 1; /* point past the quote */
347 /* ignore whitespace in quoted strings */
352 /* whitespace ended this token */
355 if (spec_match(spec_p
, s0
))
356 (*fun
) (spec_p
, s0
, calldatap
);
357 /* next string starts past the whitespace */
363 /* characters all OK inside quoted string */
368 /* start of unquoted token */
370 s0
= s
; /* token starts here */
382 * #### MISSING - need to handle quoted value strings * containing
386 for (v
= strtok_r(valstr
, " \t", &ls
); v
;
387 v
= strtok_r(NULL
, " \t", &ls
)) {
388 if (spec_match(spec_p
, v
)) {
389 (*fun
) (spec_p
, v
, calldatap
);
394 } /* end spec_valtrav */