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