/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1997, by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*LINTLIBRARY*/
#include <sys/types.h>
#include <stdlib.h>
#include "utility.h"
typedef struct {
char *leftarg;
char *rightarg;
}
LINK;
#define ArgL(n) (((LINK *)(n))->leftarg)
#define ArgR(n) (((LINK *)(n))->rightarg)
#define Ref(t) ((t)->ref)
#define TypeL(t) ((t)->left)
#define TypeR(t) ((t)->right)
#define MakeA(t) ((t)->makearg)
#define CopyA(t) ((t)->copyarg)
#define FreeA(t) ((t)->freearg)
#define Fcheck(t) ((t)->fcheck)
#define Ccheck(t) ((t)->ccheck)
#define Next(t) ((t)->next)
#define Prev(t) ((t)->prev)
/*
* default fieldtype
*/
static FIELDTYPE default_fieldtype =
{
0, /* status */
0, /* ref */
(FIELDTYPE *) 0, /* left */
(FIELDTYPE *) 0, /* right */
(PTF_charP) 0, /* makearg */
(PTF_charP) 0, /* copyarg */
(PTF_void) 0, /* freearg */
(PTF_int) 0, /* fcheck */
(PTF_int) 0, /* ccheck */
(PTF_int) 0, /* next */
(PTF_int) 0, /* prev */
};
FIELDTYPE * _DEFAULT_FIELDTYPE = &default_fieldtype;
/* new_fieldtype - field & character validation function */
FIELDTYPE *
new_fieldtype(PTF_int fcheck, PTF_int ccheck)
{
FIELDTYPE *t = (FIELDTYPE *) 0;
if ((fcheck || ccheck) && Alloc(t, FIELDTYPE)) {
*t = *_DEFAULT_FIELDTYPE;
Fcheck(t) = fcheck;
Ccheck(t) = ccheck;
}
return (t);
}
FIELDTYPE *
link_fieldtype(FIELDTYPE *left, FIELDTYPE *right)
{
FIELDTYPE *t = (FIELDTYPE *) 0;
if ((left || right) && Alloc(t, FIELDTYPE)) {
*t = *_DEFAULT_FIELDTYPE;
Set(t, LINKED);
if (Status(left, ARGS) || Status(right, ARGS))
Set(t, ARGS);
if (Status(left, CHOICE) || Status(right, CHOICE))
Set(t, CHOICE);
TypeL(t) = left;
TypeR(t) = right;
IncrType(left); /* increment reference count */
IncrType(right); /* increment reference count */
}
return (t);
}
int
free_fieldtype(FIELDTYPE *t)
{
if (!t)
return (E_BAD_ARGUMENT);
if (Ref(t))
return (E_CONNECTED);
if (Status(t, LINKED)) {
DecrType(TypeL(t)); /* decrement reference count */
DecrType(TypeR(t)); /* decrement reference count */
}
Free(t);
return (E_OK);
}
int
set_fieldtype_arg(FIELDTYPE *t, PTF_charP makearg,
PTF_charP copyarg, PTF_void freearg)
{
if (t && makearg && copyarg && freearg) {
Set(t, ARGS);
MakeA(t) = makearg;
CopyA(t) = copyarg;
FreeA(t) = freearg;
return (E_OK);
}
return (E_BAD_ARGUMENT);
}
/* set_fieldtype_choice next & prev choice function */
int
set_fieldtype_choice(FIELDTYPE *t, PTF_int next, PTF_int prev)
{
if (t && next && prev) {
Set(t, CHOICE);
Next(t) = next;
Prev(t) = prev;
return (E_OK);
}
return (E_BAD_ARGUMENT);
}
char *
_makearg(FIELDTYPE *t, va_list *ap, int *err)
{
/*
* invoke make_arg function associated with field type t.
* return pointer to argument information or null if none.
* increment err if an error is encountered.
*/
char *p = (char *)0;
if (! t || ! Status(t, ARGS))
return (p);
if (Status(t, LINKED)) {
LINK *n = (LINK *) 0;
if (Alloc(n, LINK)) {
ArgL(n) = _makearg(TypeL(t), ap, err);
ArgR(n) = _makearg(TypeR(t), ap, err);
p = (char *)n;
} else
++(*err); /* out of space */
} else
if (!(p = (*MakeA(t)) (ap)))
++(*err); /* make_arg had problem */
return (p);
}
char *
_copyarg(FIELDTYPE *t, char *arg, int *err)
{
/*
* invoke copy_arg function associated with field type t.
* return pointer to argument information or null if none.
* increment err if an error is encountered.
*/
char *p = (char *)0;
if (!t || !Status(t, ARGS))
return (p);
if (Status(t, LINKED)) {
LINK *n = (LINK *) 0;
if (Alloc(n, LINK)) {
ArgL(n) = _copyarg(TypeL(t), ArgL(arg), err);
ArgR(n) = _copyarg(TypeR(t), ArgR(arg), err);
p = (char *)n;
} else
++(*err); /* out of space */
} else
if (!(p = (*CopyA(t)) (arg)))
++(*err); /* copy_arg had problem */
return (p);
}
/* _freearg - invoke free_arg function associated with field type t. */
void
_freearg(FIELDTYPE *t, char *arg)
{
if (!t || !Status(t, ARGS))
return;
if (Status(t, LINKED)) {
_freearg(TypeL(t), ArgL(arg));
_freearg(TypeR(t), ArgR(arg));
Free(arg);
} else
(*FreeA(t)) (arg);
}
/* _checkfield - invoke check_field function associated with field type t. */
int
_checkfield(FIELDTYPE *t, FIELD *f, char *arg)
{
if (!t)
return (TRUE);
if (Opt(f, O_NULLOK)) {
char *v = Buf(f);
while (*v && *v == ' ')
++v;
if (!*v)
return (TRUE); /* empty field */
}
if (Status(t, LINKED))
return (_checkfield(TypeL(t), f, ArgL(arg)) ||
_checkfield(TypeR(t), f, ArgR(arg)));
else
if (Fcheck(t))
return ((*Fcheck(t)) (f, arg));
return (TRUE);
}
/* _checkchar - invoke check_char function associated with field type t. */
int
_checkchar(FIELDTYPE *t, int c, char *arg)
{
if (!t)
return (TRUE);
if (Status(t, LINKED))
return (_checkchar(TypeL(t), c, ArgL(arg)) ||
_checkchar(TypeR(t), c, ArgR(arg)));
else
if (Ccheck(t))
return ((*Ccheck(t)) (c, arg));
return (TRUE);
}
/* _nextchoice - invoke next_choice function associated with field type t. */
int
_nextchoice(FIELDTYPE *t, FIELD *f, char *arg)
{
if (!t || !Status(t, CHOICE))
return (FALSE);
if (Status(t, LINKED))
return (_nextchoice(TypeL(t), f, ArgL(arg)) ||
_nextchoice(TypeR(t), f, ArgR(arg)));
else
return ((*Next(t)) (f, arg));
}
/* _prevchoice - invoke prev_choice function associated with field type t. */
int
_prevchoice(FIELDTYPE *t, FIELD *f, char *arg)
{
if (!t || !Status(t, CHOICE))
return (FALSE);
if (Status(t, LINKED))
return (_prevchoice(TypeL(t), f, ArgL(arg)) ||
_prevchoice(TypeR(t), f, ArgR(arg)));
else
return ((*Prev(t)) (f, arg));
}