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