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) 1988 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  *      Copyright (c) 1997, by Sun Microsystems, Inc.
28  *      All rights reserved.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*LINTLIBRARY*/
34 
35 #include <sys/types.h>
36 #include <stdlib.h>
37 #include "utility.h"
38 
39 typedef struct {
40 	char *leftarg;
41 	char *rightarg;
42 }
43 	LINK;
44 
45 #define	ArgL(n)		(((LINK *)(n))->leftarg)
46 #define	ArgR(n)		(((LINK *)(n))->rightarg)
47 
48 #define	Ref(t)		((t)->ref)
49 #define	TypeL(t)	((t)->left)
50 #define	TypeR(t)	((t)->right)
51 #define	MakeA(t)	((t)->makearg)
52 #define	CopyA(t)	((t)->copyarg)
53 #define	FreeA(t)	((t)->freearg)
54 #define	Fcheck(t)	((t)->fcheck)
55 #define	Ccheck(t)	((t)->ccheck)
56 #define	Next(t)		((t)->next)
57 #define	Prev(t)		((t)->prev)
58 
59 	/*
60 	 *  default fieldtype
61 	 */
62 
63 static FIELDTYPE default_fieldtype =
64 {
65 			0,			/* status	*/
66 			0,			/* ref		*/
67 			(FIELDTYPE *) 0,	/* left		*/
68 			(FIELDTYPE *) 0,	/* right	*/
69 			(PTF_charP) 0,		/* makearg	*/
70 			(PTF_charP) 0,		/* copyarg	*/
71 			(PTF_void) 0,		/* freearg	*/
72 			(PTF_int) 0,		/* fcheck	*/
73 			(PTF_int) 0,		/* ccheck	*/
74 			(PTF_int) 0,		/* next		*/
75 			(PTF_int) 0,		/* prev		*/
76 };
77 
78 FIELDTYPE * _DEFAULT_FIELDTYPE	= &default_fieldtype;
79 
80 /* new_fieldtype - field & character validation function */
81 FIELDTYPE *
82 new_fieldtype(PTF_int fcheck, PTF_int ccheck)
83 {
84 	FIELDTYPE *t = (FIELDTYPE *) 0;
85 
86 	if ((fcheck || ccheck) && Alloc(t, FIELDTYPE)) {
87 		*t = *_DEFAULT_FIELDTYPE;
88 
89 		Fcheck(t) = fcheck;
90 		Ccheck(t) = ccheck;
91 	}
92 	return (t);
93 }
94 
95 FIELDTYPE *
96 link_fieldtype(FIELDTYPE *left, FIELDTYPE *right)
97 {
98 	FIELDTYPE *t = (FIELDTYPE *) 0;
99 
100 	if ((left || right) && Alloc(t, FIELDTYPE)) {
101 		*t = *_DEFAULT_FIELDTYPE;
102 
103 		Set(t, LINKED);
104 
105 		if (Status(left, ARGS) || Status(right, ARGS))
106 			Set(t, ARGS);
107 
108 		if (Status(left, CHOICE) || Status(right, CHOICE))
109 			Set(t, CHOICE);
110 
111 		TypeL(t) = left;
112 		TypeR(t) = right;
113 		IncrType(left);	/* increment reference count */
114 		IncrType(right);	/* increment reference count */
115 	}
116 	return (t);
117 }
118 
119 int
120 free_fieldtype(FIELDTYPE *t)
121 {
122 	if (!t)
123 		return (E_BAD_ARGUMENT);
124 
125 	if (Ref(t))
126 		return (E_CONNECTED);
127 
128 	if (Status(t, LINKED)) {
129 		DecrType(TypeL(t));	/* decrement reference count */
130 		DecrType(TypeR(t));	/* decrement reference count */
131 	}
132 	Free(t);
133 	return (E_OK);
134 }
135 
136 int
137 set_fieldtype_arg(FIELDTYPE *t, PTF_charP makearg,
138 	PTF_charP copyarg, PTF_void freearg)
139 {
140 	if (t && makearg && copyarg && freearg) {
141 		Set(t, ARGS);
142 		MakeA(t) = makearg;
143 		CopyA(t) = copyarg;
144 		FreeA(t) = freearg;
145 		return (E_OK);
146 	}
147 	return (E_BAD_ARGUMENT);
148 }
149 
150 /* set_fieldtype_choice next & prev choice function */
151 int
152 set_fieldtype_choice(FIELDTYPE *t, PTF_int next, PTF_int prev)
153 {
154 	if (t && next && prev) {
155 		Set(t, CHOICE);
156 		Next(t) = next;
157 		Prev(t) = prev;
158 		return (E_OK);
159 	}
160 	return (E_BAD_ARGUMENT);
161 }
162 
163 char *
164 _makearg(FIELDTYPE *t, va_list *ap, int *err)
165 {
166 /*
167  * invoke make_arg function associated with field type t.
168  * return pointer to argument information or null if none.
169  * increment err if an error is encountered.
170  */
171 	char *p = (char *)0;
172 
173 	if (! t || ! Status(t, ARGS))
174 		return (p);
175 
176 	if (Status(t, LINKED)) {
177 		LINK *n = (LINK *) 0;
178 
179 		if (Alloc(n, LINK)) {
180 			ArgL(n) = _makearg(TypeL(t), ap, err);
181 			ArgR(n) = _makearg(TypeR(t), ap, err);
182 			p = (char *)n;
183 		} else
184 			++(*err);		/* out of space */
185 	} else
186 		if (!(p = (*MakeA(t)) (ap)))
187 			++(*err);		/* make_arg had problem */
188 	return (p);
189 }
190 
191 char *
192 _copyarg(FIELDTYPE *t, char *arg, int *err)
193 {
194 /*
195  * invoke copy_arg function associated with field type t.
196  * return pointer to argument information or null if none.
197  * increment err if an error is encountered.
198  */
199 	char *p = (char *)0;
200 
201 	if (!t || !Status(t, ARGS))
202 		return (p);
203 
204 	if (Status(t, LINKED)) {
205 		LINK *n = (LINK *) 0;
206 
207 		if (Alloc(n, LINK)) {
208 			ArgL(n) = _copyarg(TypeL(t), ArgL(arg), err);
209 			ArgR(n) = _copyarg(TypeR(t), ArgR(arg), err);
210 			p = (char *)n;
211 		} else
212 			++(*err);		/* out of space */
213 	} else
214 		if (!(p = (*CopyA(t)) (arg)))
215 			++(*err);		/* copy_arg had problem */
216 	return (p);
217 }
218 
219 /* _freearg - invoke free_arg function associated with field type t.  */
220 void
221 _freearg(FIELDTYPE *t, char *arg)
222 {
223 	if (!t || !Status(t, ARGS))
224 		return;
225 
226 	if (Status(t, LINKED)) {
227 		_freearg(TypeL(t), ArgL(arg));
228 		_freearg(TypeR(t), ArgR(arg));
229 		Free(arg);
230 	} else
231 		(*FreeA(t)) (arg);
232 }
233 
234 /* _checkfield - invoke check_field function associated with field type t.  */
235 int
236 _checkfield(FIELDTYPE *t, FIELD *f, char *arg)
237 {
238 	if (!t)
239 		return (TRUE);
240 
241 	if (Opt(f, O_NULLOK)) {
242 		char *v = Buf(f);
243 
244 		while (*v && *v == ' ')
245 			++v;
246 		if (!*v)
247 			return (TRUE);	/* empty field */
248 	}
249 	if (Status(t, LINKED))
250 		return	(_checkfield(TypeL(t), f, ArgL(arg)) ||
251 		    _checkfield(TypeR(t), f, ArgR(arg)));
252 	else
253 		if (Fcheck(t))
254 			return ((*Fcheck(t)) (f, arg));
255 	return (TRUE);
256 }
257 
258 /* _checkchar - invoke check_char function associated with field type t.  */
259 int
260 _checkchar(FIELDTYPE *t, int c, char *arg)
261 {
262 	if (!t)
263 		return (TRUE);
264 
265 	if (Status(t, LINKED))
266 		return	(_checkchar(TypeL(t), c, ArgL(arg)) ||
267 		    _checkchar(TypeR(t), c, ArgR(arg)));
268 	else
269 		if (Ccheck(t))
270 			return ((*Ccheck(t)) (c, arg));
271 	return (TRUE);
272 }
273 
274 /* _nextchoice - invoke next_choice function associated with field type t.  */
275 int
276 _nextchoice(FIELDTYPE *t, FIELD *f, char *arg)
277 {
278 	if (!t || !Status(t, CHOICE))
279 		return (FALSE);
280 
281 	if (Status(t, LINKED))
282 		return	(_nextchoice(TypeL(t), f, ArgL(arg)) ||
283 		    _nextchoice(TypeR(t), f, ArgR(arg)));
284 	else
285 		return ((*Next(t)) (f, arg));
286 }
287 
288 /* _prevchoice - invoke prev_choice function associated with field type t. */
289 int
290 _prevchoice(FIELDTYPE *t, FIELD *f, char *arg)
291 {
292 	if (!t || !Status(t, CHOICE))
293 		return (FALSE);
294 
295 	if (Status(t, LINKED))
296 		return	(_prevchoice(TypeL(t), f, ArgL(arg)) ||
297 		    _prevchoice(TypeR(t), f, ArgR(arg)));
298 	else
299 		return ((*Prev(t)) (f, arg));
300 }
301