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
39typedef 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
63static 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
78FIELDTYPE * _DEFAULT_FIELDTYPE	= &default_fieldtype;
79
80/* new_fieldtype - field & character validation function */
81FIELDTYPE *
82new_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
95FIELDTYPE *
96link_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
119int
120free_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
136int
137set_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 */
151int
152set_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
163char *
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
191char *
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.  */
220void
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.  */
235int
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.  */
259int
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.  */
275int
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. */
289int
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