#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)
static FIELDTYPE default_fieldtype =
{
0,
0,
(FIELDTYPE *) 0,
(FIELDTYPE *) 0,
(PTF_charP) 0,
(PTF_charP) 0,
(PTF_void) 0,
(PTF_int) 0,
(PTF_int) 0,
(PTF_int) 0,
(PTF_int) 0,
};
FIELDTYPE * _DEFAULT_FIELDTYPE = &default_fieldtype;
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);
IncrType(right);
}
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));
DecrType(TypeR(t));
}
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);
}
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)
{
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);
} else
if (!(p = (*MakeA(t)) (ap)))
++(*err);
return (p);
}
char *
_copyarg(FIELDTYPE *t, char *arg, int *err)
{
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);
} else
if (!(p = (*CopyA(t)) (arg)))
++(*err);
return (p);
}
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);
}
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);
}
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);
}
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);
}
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));
}
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));
}