Blame src/cmd/ksh93/sh/nvtype.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1982-2012 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#pragma prototyped
Packit Service a8c26c
/*
Packit Service a8c26c
 * David Korn
Packit Service a8c26c
 * AT&T Labs
Packit Service a8c26c
 *
Packit Service a8c26c
 */
Packit Service a8c26c
#include        "defs.h"
Packit Service a8c26c
#include        "io.h"
Packit Service a8c26c
#include        "variables.h"
Packit Service a8c26c
Packit Service a8c26c
static const char sh_opttype[] =
Packit Service a8c26c
"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-07-01 $\n]"
Packit Service a8c26c
USAGE_LICENSE
Packit Service a8c26c
"[+NAME?\f?\f - set the type of variables to \b\f?\f\b]"
Packit Service a8c26c
"[+DESCRIPTION?\b\f?\f\b sets the type on each of the variables specified "
Packit Service a8c26c
	"by \aname\a to \b\f?\f\b. If \b=\b\avalue\a is specified, "
Packit Service a8c26c
	"the variable \aname\a is set to \avalue\a before the variable "
Packit Service a8c26c
	"is converted to \b\f?\f\b.]"
Packit Service a8c26c
"[+?If no \aname\as are specified then the names and values of all "
Packit Service a8c26c
	"variables of this type are written to standard output.]" 
Packit Service a8c26c
"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
Packit Service a8c26c
	"field splitting and pathname expansion are not performed on "
Packit Service a8c26c
	"the arguments.  Tilde expansion occurs on \avalue\a.]"
Packit Service a8c26c
"[r?Enables readonly.  Once enabled, the value cannot be changed or unset.]"
Packit Service a8c26c
"[a]:?[type?Indexed array. Each \aname\a will converted to an index "
Packit Service a8c26c
	"array of type \b\f?\f\b.  If a variable already exists, the current "
Packit Service a8c26c
	"value will become index \b0\b.  If \b[\b\atype\a\b]]\b is "
Packit Service a8c26c
	"specified, each subscript is interpreted as a value of enumeration "
Packit Service a8c26c
	"type \atype\a.]"
Packit Service a8c26c
"[A?Associative array.  Each \aname\a will converted to an associate "
Packit Service a8c26c
        "array of type \b\f?\f\b.  If a variable already exists, the current "
Packit Service a8c26c
	"value will become subscript \b0\b.]"
Packit Service a8c26c
"[h]:[string?Used within a type definition to provide a help string  "
Packit Service a8c26c
	"for variable \aname\a.  Otherwise, it is ignored.]"
Packit Service a8c26c
"[S?Used with a type definition to indicate that the variable is shared by "
Packit Service a8c26c
	"each instance of the type.  When used inside a function defined "
Packit Service a8c26c
	"with the \bfunction\b reserved word, the specified variables "
Packit Service a8c26c
	"will have function static scope.  Otherwise, the variable is "
Packit Service a8c26c
	"unset prior to processing the assignment list.]"
Packit Service a8c26c
"[+DETAILS]\ftypes\f"
Packit Service a8c26c
"\n"
Packit Service a8c26c
"\n[name[=value]...]\n"
Packit Service a8c26c
"\n"
Packit Service a8c26c
"[+EXIT STATUS?]{"
Packit Service a8c26c
        "[+0?Successful completion.]"
Packit Service a8c26c
        "[+>0?An error occurred.]"
Packit Service a8c26c
"}"
Packit Service a8c26c
Packit Service a8c26c
"[+SEE ALSO?\fother\f \breadonly\b(1), \btypeset\b(1)]"
Packit Service a8c26c
;
Packit Service a8c26c
Packit Service a8c26c
typedef struct Namtype Namtype_t;
Packit Service a8c26c
typedef struct Namchld
Packit Service a8c26c
{
Packit Service a8c26c
	Namfun_t	fun;
Packit Service a8c26c
	Namtype_t 	*ptype;
Packit Service a8c26c
	Namtype_t 	*ttype;
Packit Service a8c26c
} Namchld_t;
Packit Service a8c26c
Packit Service a8c26c
struct Namtype
Packit Service a8c26c
{
Packit Service a8c26c
	Namfun_t	fun;
Packit Service a8c26c
	Shell_t		*sh;
Packit Service a8c26c
	Namval_t	*np;
Packit Service a8c26c
	Namval_t	*parent;
Packit Service a8c26c
	Namval_t	*bp;
Packit Service a8c26c
	Namval_t	*cp;
Packit Service a8c26c
#if SHOPT_NAMESPACE
Packit Service a8c26c
	Namval_t	*nsp;
Packit Service a8c26c
#endif /* SHOPT_NAMESPACE */
Packit Service a8c26c
	char		*nodes;
Packit Service a8c26c
	char		*data;
Packit Service a8c26c
	Namchld_t	childfun;
Packit Service a8c26c
	int		numnodes;
Packit Service a8c26c
	char		**names;
Packit Service a8c26c
	size_t		dsize;
Packit Service a8c26c
	short		strsize;
Packit Service a8c26c
	unsigned short	ndisc;
Packit Service a8c26c
	unsigned short	current;
Packit Service a8c26c
	unsigned short	nref;
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
#if 0
Packit Service a8c26c
struct type
Packit Service a8c26c
{
Packit Service a8c26c
	Namtype_t	hdr;
Packit Service a8c26c
	unsigned short	ndisc;
Packit Service a8c26c
	unsigned short	current;
Packit Service a8c26c
	unsigned short	nref;
Packit Service a8c26c
};
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
typedef struct
Packit Service a8c26c
{
Packit Service a8c26c
	char		_cSfdouble_t;
Packit Service a8c26c
	Sfdouble_t	_dSfdouble_t;
Packit Service a8c26c
	char		_cdouble;
Packit Service a8c26c
	double		_ddouble;
Packit Service a8c26c
	char		_cfloat;
Packit Service a8c26c
	float		_dfloat;
Packit Service a8c26c
	char		_cSflong_t;
Packit Service a8c26c
	Sflong_t	_dSflong_t;
Packit Service a8c26c
	char		_clong;
Packit Service a8c26c
	long		_dlong;
Packit Service a8c26c
	char		_cshort;
Packit Service a8c26c
	short		_dshort;
Packit Service a8c26c
	char		_cpointer;
Packit Service a8c26c
	char		*_dpointer;
Packit Service a8c26c
	int32_t		_cint32_t;
Packit Service a8c26c
	int32_t		*_dint32_t;
Packit Service a8c26c
} _Align_;
Packit Service a8c26c
Packit Service a8c26c
#define alignof(t)	((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
Packit Service a8c26c
Packit Service a8c26c
static void put_type(Namval_t*, const char*, int, Namfun_t*);
Packit Service a8c26c
static Namval_t* create_type(Namval_t*, const char*, int, Namfun_t*);
Packit Service a8c26c
static Namfun_t* clone_type(Namval_t*, Namval_t*, int, Namfun_t*);
Packit Service a8c26c
static Namval_t* next_type(Namval_t*, Dt_t*, Namfun_t*);
Packit Service a8c26c
Packit Service a8c26c
static const Namdisc_t type_disc =
Packit Service a8c26c
{
Packit Service a8c26c
	sizeof(Namtype_t),
Packit Service a8c26c
	put_type,
Packit Service a8c26c
	0,
Packit Service a8c26c
	0,
Packit Service a8c26c
	0,
Packit Service a8c26c
	create_type,
Packit Service a8c26c
	clone_type,
Packit Service a8c26c
	0,
Packit Service a8c26c
	next_type,
Packit Service a8c26c
	0,
Packit Service a8c26c
#if 0
Packit Service a8c26c
	read_type
Packit Service a8c26c
#endif
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
size_t nv_datasize(Namval_t *np, size_t *offset)
Packit Service a8c26c
{
Packit Service a8c26c
	size_t s=0, a=0;
Packit Service a8c26c
	if(nv_isattr(np,NV_INTEGER))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(nv_isattr(np, NV_LONG))
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(Sfdouble_t);
Packit Service a8c26c
				s = sizeof(Sfdouble_t);
Packit Service a8c26c
			}
Packit Service a8c26c
			else if(nv_isattr(np, NV_SHORT))
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(float);
Packit Service a8c26c
				s = sizeof(float);
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(double);
Packit Service a8c26c
				s = sizeof(double);
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			if(nv_isattr(np, NV_LONG))
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(Sflong_t);
Packit Service a8c26c
				s = sizeof(Sflong_t);
Packit Service a8c26c
			}
Packit Service a8c26c
			else if(nv_isattr(np, NV_SHORT))
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(short);
Packit Service a8c26c
				s = sizeof(short);
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
			{
Packit Service a8c26c
				a = alignof(int32_t);
Packit Service a8c26c
				s = sizeof(int32_t);
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(nv_isattr(np, NV_BINARY) || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
Packit Service a8c26c
		s = nv_size(np);
Packit Service a8c26c
	else
Packit Service a8c26c
	{
Packit Service a8c26c
		a = alignof(pointer);
Packit Service a8c26c
		s = nv_size(np);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(a>1 && offset)
Packit Service a8c26c
		*offset = a*((*offset +a-1)/a);
Packit Service a8c26c
	return(s);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static char *name_chtype(Namval_t *np, Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namchld_t	*pp = (Namchld_t*)fp;
Packit Service a8c26c
	char		*cp, *sub;
Packit Service a8c26c
	Namval_t	*tp = sh.last_table;
Packit Service a8c26c
	Namval_t	*nq = pp->ptype->np;
Packit Service a8c26c
	Namarr_t	*ap;
Packit Service a8c26c
	if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
Packit Service a8c26c
		sh.last_table = 0;
Packit Service a8c26c
	cp = nv_name(nq);
Packit Service a8c26c
	if((ap = nv_arrayptr(nq)) && !(ap->nelem&ARRAY_UNDEF) && (sub= nv_getsub(nq)))
Packit Service a8c26c
		sfprintf(sh.strbuf,"%s[%s].%s",cp,sub,np->nvname);
Packit Service a8c26c
	else
Packit Service a8c26c
		sfprintf(sh.strbuf,"%s.%s",cp,np->nvname);
Packit Service a8c26c
#if SHOPT_FIXEDARRAY
Packit Service a8c26c
	if((ap=nv_arrayptr(np)) && ap->fixed)
Packit Service a8c26c
		nv_arrfixed(np,sh.strbuf,1,(char*)0);
Packit Service a8c26c
#endif /* SHOPT_FIXEDARRAY */
Packit Service a8c26c
	sh.last_table = tp;
Packit Service a8c26c
	return(sfstruse(sh.strbuf));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static void put_chtype(Namval_t* np, const char* val, int flag, Namfun_t* fp)
Packit Service a8c26c
{
Packit Service a8c26c
	if(!val && nv_isattr(np,NV_REF))
Packit Service a8c26c
		return;
Packit Service a8c26c
	nv_putv(np,val,flag,fp);
Packit Service a8c26c
	if(!val)
Packit Service a8c26c
	{
Packit Service a8c26c
		Namchld_t	*pp = (Namchld_t*)fp;
Packit Service a8c26c
		size_t		dsize=0,offset = (char*)np-(char*)pp->ptype;
Packit Service a8c26c
		Namval_t	*mp = (Namval_t*)((char*)pp->ttype+offset);
Packit Service a8c26c
		dsize = nv_datasize(mp,&dsize);
Packit Service a8c26c
		if(mp->nvalue.cp >=  pp->ttype->data && mp->nvalue.cp < (char*)pp+pp->ttype->fun.dsize)
Packit Service a8c26c
		{
Packit Service a8c26c
			np->nvalue.cp = pp->ptype->data + (mp->nvalue.cp-pp->ptype->data);
Packit Service a8c26c
			if(np->nvalue.cp!=mp->nvalue.cp)
Packit Service a8c26c
				memcpy((char*)np->nvalue.cp,mp->nvalue.cp,dsize);
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(!nv_isarray(mp) && mp->nvalue.cp)
Packit Service a8c26c
		{
Packit Service a8c26c
			np->nvalue.cp = mp->nvalue.cp;
Packit Service a8c26c
			nv_onattr(np,NV_NOFREE);
Packit Service a8c26c
		}
Packit Service a8c26c
		np->nvsize = mp->nvsize;
Packit Service a8c26c
		np->nvflag = mp->nvflag&~NV_RDONLY;
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Namfun_t *clone_chtype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	if(flags&NV_NODISC)
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	return(nv_clone_disc(fp,flags));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static const Namdisc_t chtype_disc =
Packit Service a8c26c
{
Packit Service a8c26c
	sizeof(Namchld_t),
Packit Service a8c26c
	put_chtype,
Packit Service a8c26c
	0,
Packit Service a8c26c
	0,
Packit Service a8c26c
	0,
Packit Service a8c26c
	0,
Packit Service a8c26c
	clone_chtype,
Packit Service a8c26c
	name_chtype
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
static Namval_t *findref(void *nodes, int n)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*tp,*np = nv_namptr(nodes,n);
Packit Service a8c26c
	char		*name = np->nvname;
Packit Service a8c26c
	int		i=n, len= strrchr(name,'.')-name;
Packit Service a8c26c
	Namtype_t	*pp;
Packit Service a8c26c
	while(--i>0)
Packit Service a8c26c
	{
Packit Service a8c26c
		np = nv_namptr(nodes,i);
Packit Service a8c26c
		if(np->nvname[len]==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			tp = nv_type(np);
Packit Service a8c26c
			pp = (Namtype_t*)nv_hasdisc(tp,&type_disc);
Packit Service a8c26c
			return(nv_namptr(pp->nodes,n-i-1));
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static int fixnode(Namtype_t *dp, Namtype_t *pp, int i, struct Namref *nrp,int flag)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*nq = nv_namptr(dp->nodes,i);
Packit Service a8c26c
	Namfun_t	*fp;
Packit Service a8c26c
	if(fp=nv_hasdisc(nq,&chtype_disc))
Packit Service a8c26c
		nv_disc(nq, fp, NV_POP);
Packit Service a8c26c
	if(nv_isattr(nq,NV_REF))
Packit Service a8c26c
	{
Packit Service a8c26c
		nq->nvalue.nrp = nrp++;
Packit Service a8c26c
		nv_setsize(nq,0);
Packit Service a8c26c
		if(strchr(nq->nvname,'.'))
Packit Service a8c26c
			nq->nvalue.nrp->np = findref(dp->nodes,i);
Packit Service a8c26c
		else
Packit Service a8c26c
			nq->nvalue.nrp->np = nv_namptr(pp->childfun.ttype->nodes,i);
Packit Service a8c26c
		nq->nvalue.nrp->root = sh.last_root;
Packit Service a8c26c
		nq->nvalue.nrp->table = pp->np;
Packit Service a8c26c
		nq ->nvflag = NV_REF|NV_NOFREE|NV_MINIMAL;
Packit Service a8c26c
		return(1);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(nq->nvalue.cp || nq->nvfun)
Packit Service a8c26c
	{
Packit Service a8c26c
		const char *data = nq->nvalue.cp;
Packit Service a8c26c
		if(nq->nvfun)
Packit Service a8c26c
		{
Packit Service a8c26c
			Namval_t *np = nv_namptr(pp->nodes,i);
Packit Service a8c26c
			if(nv_isarray(nq))
Packit Service a8c26c
				nq->nvalue.cp = 0;
Packit Service a8c26c
			nq->nvfun = 0;
Packit Service a8c26c
			if(nv_isarray(nq) && ((flag&NV_IARRAY) || nv_type(np)))
Packit Service a8c26c
				clone_all_disc(np,nq,flag&~NV_TYPE);
Packit Service a8c26c
			else
Packit Service a8c26c
				clone_all_disc(np,nq,flag);
Packit Service a8c26c
			if(fp)
Packit Service a8c26c
				nv_disc(np, fp, NV_LAST);
Packit Service a8c26c
		}
Packit Service a8c26c
#if 0
Packit Service a8c26c
		if(nq->nvalue.cp >=  pp->data && nq->nvalue.cp < (char*)pp +pp->fun.dsize)
Packit Service a8c26c
			nq->nvalue.cp = dp->data + (nq->nvalue.cp-pp->data);
Packit Service a8c26c
#else
Packit Service a8c26c
		if(data >=  pp->data && data < (char*)pp +pp->fun.dsize)
Packit Service a8c26c
			nq->nvalue.cp = dp->data + (data-pp->data);
Packit Service a8c26c
#endif
Packit Service a8c26c
		else if(!nq->nvfun && pp->childfun.ttype!=pp->childfun.ptype)
Packit Service a8c26c
		{
Packit Service a8c26c
			Namval_t *nr = nv_namptr( pp->childfun.ttype->nodes,i);
Packit Service a8c26c
			if(nr->nvalue.cp!=nq->nvalue.cp)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(i=nv_size(nq))
Packit Service a8c26c
				{
Packit Service a8c26c
					const char *cp = nq->nvalue.cp;
Packit Service a8c26c
					nq->nvalue.cp = (char*)malloc(i);
Packit Service a8c26c
					memcpy((char*)nq->nvalue.cp,cp,i);
Packit Service a8c26c
				}
Packit Service a8c26c
				else
Packit Service a8c26c
					nq->nvalue.cp = strdup(nq->nvalue.cp);
Packit Service a8c26c
				nv_offattr(nq,NV_NOFREE);
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(nq->nvalue.cp==Empty)
Packit Service a8c26c
			nv_offattr(nq,NV_NOFREE);
Packit Service a8c26c
	
Packit Service a8c26c
	}
Packit Service a8c26c
	if(fp)
Packit Service a8c26c
		nv_disc(nq, &dp->childfun.fun, NV_LAST);
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Namfun_t *clone_type(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namtype_t		*dp, *pp=(Namtype_t*)fp;
Packit Service a8c26c
	register int		i;
Packit Service a8c26c
	register Namval_t	*nq, *nr;
Packit Service a8c26c
	size_t			size = fp->dsize;
Packit Service a8c26c
	int			save, offset=staktell();
Packit Service a8c26c
	char			*cp;
Packit Service a8c26c
	Dt_t			*root = sh.last_root;
Packit Service a8c26c
	Namval_t		*last_table = sh.last_table;
Packit Service a8c26c
	struct Namref		*nrp = 0;
Packit Service a8c26c
	Namarr_t		*ap;
Packit Service a8c26c
	if(flags&NV_MOVE)
Packit Service a8c26c
	{
Packit Service a8c26c
		pp->np = mp;
Packit Service a8c26c
		pp->childfun.ptype = pp;
Packit Service a8c26c
		return(fp);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(flags&NV_TYPE)
Packit Service a8c26c
		return(nv_clone_disc(fp,flags));
Packit Service a8c26c
	if(size==0 && (!fp->disc || (size=fp->disc->dsize)==0)) 
Packit Service a8c26c
		size = sizeof(Namfun_t);
Packit Service a8c26c
	dp = (Namtype_t*)malloc(size+pp->nref*sizeof(struct Namref));
Packit Service a8c26c
	if(pp->nref)
Packit Service a8c26c
	{
Packit Service a8c26c
		nrp = (struct Namref*)((char*)dp + size);
Packit Service a8c26c
		memset((void*)nrp,0,pp->nref*sizeof(struct Namref));
Packit Service a8c26c
	}
Packit Service a8c26c
	memcpy((void*)dp,(void*)pp,size);
Packit Service a8c26c
#if 0
Packit Service a8c26c
	dp->parent = nv_lastdict();
Packit Service a8c26c
#else
Packit Service a8c26c
	dp->parent = mp;
Packit Service a8c26c
#endif
Packit Service a8c26c
	dp->fun.nofree = (flags&NV_RDONLY?1:0);
Packit Service a8c26c
	dp->np = mp;
Packit Service a8c26c
	dp->childfun.ptype = dp;
Packit Service a8c26c
#if 0
Packit Service a8c26c
	dp->childfun.ttype = (Namtype_t*)nv_hasdisc(dp->fun.type,&type_disc);
Packit Service a8c26c
#endif
Packit Service a8c26c
	dp->nodes = (char*)(dp+1);
Packit Service a8c26c
	dp->data = (char*)dp + (pp->data - (char*)pp);
Packit Service a8c26c
	for(i=dp->numnodes; --i >= 0; )
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(dp->nodes,i);
Packit Service a8c26c
		if(fixnode(dp,pp,i,nrp,NV_TYPE|(flags&NV_IARRAY)))
Packit Service a8c26c
		{
Packit Service a8c26c
			nrp++;
Packit Service a8c26c
			nq = nq->nvalue.nrp->np;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(flags==(NV_NOFREE|NV_ARRAY))
Packit Service a8c26c
			continue;
Packit Service a8c26c
		if(nq->nvalue.cp || !nv_isvtree(nq) || nv_isattr(nq,NV_RDONLY))
Packit Service a8c26c
		{
Packit Service a8c26c
			/* see if default value has been overwritten */
Packit Service a8c26c
			if(!mp->nvname)
Packit Service a8c26c
				continue;
Packit Service a8c26c
			sh.last_table = last_table;
Packit Service a8c26c
			if(pp->strsize<0)
Packit Service a8c26c
				cp = nv_name(np);
Packit Service a8c26c
			else
Packit Service a8c26c
				cp = nv_name(mp);
Packit Service a8c26c
			stakputs(cp);
Packit Service a8c26c
			stakputc('.');
Packit Service a8c26c
			stakputs(nq->nvname);
Packit Service a8c26c
			stakputc(0);
Packit Service a8c26c
			root = nv_dict(mp);
Packit Service a8c26c
			save = fp->nofree;
Packit Service a8c26c
			fp->nofree = 1;
Packit Service a8c26c
			nr = nv_create(stakptr(offset),root,NV_VARNAME|NV_NOADD,fp);
Packit Service a8c26c
			fp->nofree = save;
Packit Service a8c26c
			stakseek(offset);
Packit Service a8c26c
			if(nr)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(nv_isattr(nq,NV_RDONLY) && (nq->nvalue.cp || nv_isattr(nq,NV_INTEGER)))
Packit Service a8c26c
					errormsg(SH_DICT,ERROR_exit(1),e_readonly, nq->nvname);
Packit Service a8c26c
				if(nv_isref(nq))
Packit Service a8c26c
					nq = nv_refnode(nq);
Packit Service a8c26c
				if((size = nv_datasize(nr,(size_t*)0)) && size==nv_datasize(nq,(size_t*)0))
Packit Service a8c26c
					memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size);
Packit Service a8c26c
				else if(ap=nv_arrayptr(nr))
Packit Service a8c26c
				{
Packit Service a8c26c
					nv_putsub(nr,NIL(char*),ARRAY_SCAN|ARRAY_NOSCOPE);
Packit Service a8c26c
					do
Packit Service a8c26c
					{
Packit Service a8c26c
						if(array_assoc(ap))
Packit Service a8c26c
							cp = (char*)((*ap->fun)(nr,NIL(char*),NV_ANAME));
Packit Service a8c26c
						else
Packit Service a8c26c
							cp = nv_getsub(nr);
Packit Service a8c26c
						nv_putsub(nq,cp,ARRAY_ADD|ARRAY_NOSCOPE);
Packit Service a8c26c
						if(array_assoc(ap))
Packit Service a8c26c
						{
Packit Service a8c26c
							Namval_t *mp = (Namval_t*)((*ap->fun)(nr,NIL(char*),NV_ACURRENT));
Packit Service a8c26c
							Namval_t *mq = (Namval_t*)((*ap->fun)(nq,NIL(char*),NV_ACURRENT));
Packit Service a8c26c
							nv_clone(mp,mq,NV_MOVE);
Packit Service a8c26c
							ap->nelem--;
Packit Service a8c26c
							nv_delete(mp,ap->table,0);
Packit Service a8c26c
						}
Packit Service a8c26c
						else
Packit Service a8c26c
						{
Packit Service a8c26c
							cp = nv_getval(nr);
Packit Service a8c26c
							nv_putval(nq,cp,0);
Packit Service a8c26c
						}
Packit Service a8c26c
					}
Packit Service a8c26c
					while(nv_nextsub(nr));
Packit Service a8c26c
				}
Packit Service a8c26c
				else
Packit Service a8c26c
					nv_putval(nq,nv_getval(nr),NV_RDONLY);
Packit Service a8c26c
#if SHOPT_TYPEDEF
Packit Service a8c26c
				if(sh.mktype)
Packit Service a8c26c
					nv_addnode(nr,1);
Packit Service a8c26c
#endif /* SHOPT_TYPEDEF */
Packit Service a8c26c
				if(pp->strsize<0)
Packit Service a8c26c
					continue;
Packit Service a8c26c
				_nv_unset(nr,0);
Packit Service a8c26c
				if(!nv_isattr(nr,NV_MINIMAL))
Packit Service a8c26c
					nv_delete(nr,sh.last_root,0);
Packit Service a8c26c
			}
Packit Service a8c26c
			else if(nv_isattr(nq,NV_RDONLY) && !nq->nvalue.cp && !nv_isattr(nq,NV_INTEGER))
Packit Service a8c26c
				errormsg(SH_DICT,ERROR_exit(1),e_required,nq->nvname,nv_name(mp));
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	if(nv_isattr(mp,NV_BINARY))
Packit Service a8c26c
		mp->nvalue.cp = dp->data;
Packit Service a8c26c
	if(pp->strsize<0)
Packit Service a8c26c
		dp->strsize = -pp->strsize;
Packit Service a8c26c
	return(&dp->fun);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * return Namval_t* corresponding to child <name> in <np>
Packit Service a8c26c
 */
Packit Service a8c26c
static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namtype_t		*dp = (Namtype_t*)fp;
Packit Service a8c26c
	register const char	*cp=name;
Packit Service a8c26c
	register int		i=0,n;
Packit Service a8c26c
	Namval_t		*nq=0;
Packit Service a8c26c
	if(!name)
Packit Service a8c26c
		return(dp->parent);
Packit Service a8c26c
	while((n=*cp++) && n != '=' && n != '+' && n!='[');
Packit Service a8c26c
	n = (cp-1) -name;
Packit Service a8c26c
	if(dp->numnodes && dp->strsize<0)
Packit Service a8c26c
	{
Packit Service a8c26c
		char *base =  (char*)np-sizeof(Dtlink_t);
Packit Service a8c26c
		int m=strlen(np->nvname);
Packit Service a8c26c
		while((nq=nv_namptr(base,++i)) && memcmp(nq->nvname,np->nvname,m)==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(nq->nvname[m]=='.' && memcmp(name,&nq->nvname[m+1],n)==0 && nq->nvname[m+n+1]==0)
Packit Service a8c26c
				goto found;
Packit Service a8c26c
		}
Packit Service a8c26c
		nq = 0;
Packit Service a8c26c
	}
Packit Service a8c26c
	else for(i=0; i < dp->numnodes; i++)
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(dp->nodes,i);
Packit Service a8c26c
		if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			while(nv_isref(nq))
Packit Service a8c26c
				nq = nq->nvalue.nrp->np;
Packit Service a8c26c
			goto found;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	nq = 0;
Packit Service a8c26c
found:
Packit Service a8c26c
	if(nq)
Packit Service a8c26c
	{
Packit Service a8c26c
		fp->last = (char*)&name[n];
Packit Service a8c26c
		sh.last_table = dp->parent;
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
	{
Packit Service a8c26c
		if(name[n]!='=') for(i=0; i < dp->ndisc; i++)
Packit Service a8c26c
		{
Packit Service a8c26c
			if((memcmp(name,dp->names[i],n)==0) && dp->names[i][n]==0)
Packit Service a8c26c
				return(nq);
Packit Service a8c26c
		}
Packit Service a8c26c
		errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
Packit Service a8c26c
	}
Packit Service a8c26c
	return(nq);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static void put_type(Namval_t* np, const char* val, int flag, Namfun_t* fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*nq;
Packit Service a8c26c
	if(val && (nq=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL))) 
Packit Service a8c26c
	{
Packit Service a8c26c
		Namfun_t  *pp;
Packit Service a8c26c
		if((pp=nv_hasdisc(nq,fp->disc)) && pp->type==fp->type)
Packit Service a8c26c
Packit Service a8c26c
		{
Packit Service a8c26c
			if(!nq->nvenv)
Packit Service a8c26c
				flag |= NV_EXPORT;
Packit Service a8c26c
			_nv_unset(np, flag);
Packit Service a8c26c
			nv_clone(nq,np,NV_IARRAY);
Packit Service a8c26c
			return;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	nv_putv(np,val,flag,fp);
Packit Service a8c26c
	if(!val)
Packit Service a8c26c
	{
Packit Service a8c26c
		Namtype_t	*dp = (Namtype_t*)fp;
Packit Service a8c26c
		Namval_t	*nq;
Packit Service a8c26c
		Namarr_t	*ap;
Packit Service a8c26c
		int		i;
Packit Service a8c26c
		if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
Packit Service a8c26c
			return;
Packit Service a8c26c
		for(i=0; i < dp->numnodes; i++)
Packit Service a8c26c
		{
Packit Service a8c26c
			nq = nv_namptr(dp->nodes,i);
Packit Service a8c26c
			if(ap=nv_arrayptr(nq))
Packit Service a8c26c
				ap->nelem |= ARRAY_UNDEF;
Packit Service a8c26c
			if(!nv_hasdisc(nq,&type_disc))
Packit Service a8c26c
				_nv_unset(nq,flag|NV_TYPE|nv_isattr(nq,NV_RDONLY));
Packit Service a8c26c
		}
Packit Service a8c26c
		nv_disc(np,fp,NV_POP);
Packit Service a8c26c
		if(!(fp->nofree&1))
Packit Service a8c26c
			free((void*)fp);
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Namval_t *next_type(register Namval_t* np, Dt_t *root,Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namtype_t	*dp = (Namtype_t*)fp;
Packit Service a8c26c
	if(!root)
Packit Service a8c26c
	{
Packit Service a8c26c
		Namarr_t	*ap = nv_arrayptr(np);
Packit Service a8c26c
		if(ap && (ap->nelem&ARRAY_UNDEF))
Packit Service a8c26c
			nv_putsub(np,(char*)0,ARRAY_SCAN);
Packit Service a8c26c
		dp->current = 0;
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(++dp->current>=dp->numnodes)
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	return(nv_namptr(dp->nodes,dp->current));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Namfun_t *clone_inttype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	Namfun_t	*pp=  (Namfun_t*)malloc(fp->dsize);
Packit Service a8c26c
	memcpy((void*)pp, (void*)fp, fp->dsize);
Packit Service a8c26c
	fp->nofree &= ~1;
Packit Service a8c26c
	if(nv_isattr(mp,NV_NOFREE) && mp->nvalue.cp)
Packit Service a8c26c
		memcpy((void*)mp->nvalue.cp,np->nvalue.cp, fp->dsize-sizeof(*fp));
Packit Service a8c26c
	else
Packit Service a8c26c
		mp->nvalue.cp = (char*)(fp+1);
Packit Service a8c26c
	if(!nv_isattr(mp,NV_MINIMAL))
Packit Service a8c26c
		mp->nvenv = 0;
Packit Service a8c26c
	nv_offattr(mp,NV_RDONLY);
Packit Service a8c26c
	return(pp);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static int typeinfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
Packit Service a8c26c
{
Packit Service a8c26c
	char		*cp,**help,buffer[256];
Packit Service a8c26c
	Namtype_t	*dp;
Packit Service a8c26c
	Namval_t	*np,*nq,*tp;
Packit Service a8c26c
	int		n, i, offset=staktell();
Packit Service a8c26c
	Sfio_t		*sp;
Packit Service a8c26c
	
Packit Service a8c26c
	np = *(Namval_t**)(fp+1);
Packit Service a8c26c
	stakputs(NV_CLASS);
Packit Service a8c26c
	stakputc('.');
Packit Service a8c26c
	stakputs(np->nvname);
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	np = nv_open(cp=stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME);
Packit Service a8c26c
	stakseek(offset);
Packit Service a8c26c
	if(!np)
Packit Service a8c26c
	{
Packit Service a8c26c
		sfprintf(sfstderr,"%s: no such variable\n",cp);
Packit Service a8c26c
		return(-1);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(!(dp=(Namtype_t*)nv_hasdisc(np,&type_disc)))
Packit Service a8c26c
	{
Packit Service a8c26c
		Namfun_t *fp;
Packit Service a8c26c
		for(fp=np->nvfun;fp;fp=fp->next)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(fp->disc && fp->disc->clonef==clone_inttype)
Packit Service a8c26c
				break;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(!fp)
Packit Service a8c26c
		{
Packit Service a8c26c
			sfprintf(sfstderr,"%s: not a type\n",np->nvname);
Packit Service a8c26c
			return(-1);
Packit Service a8c26c
		}
Packit Service a8c26c
		if(strcmp(str,"other")==0)
Packit Service a8c26c
			return(0);
Packit Service a8c26c
		tp = fp->type;
Packit Service a8c26c
		nv_offattr(np,NV_RDONLY);
Packit Service a8c26c
		fp->type = 0;
Packit Service a8c26c
		if(np->nvenv)
Packit Service a8c26c
			sfprintf(out,"[+?\b%s\b is a %s.]\n", tp->nvname, np->nvenv);
Packit Service a8c26c
		cp = (char*)out->_next;
Packit Service a8c26c
		sfprintf(out,"[+?\b%s\b is a %n ", tp->nvname, &i);
Packit Service a8c26c
		nv_attribute(np,out,(char*)0, 1);
Packit Service a8c26c
		if(cp[i+1]=='i')
Packit Service a8c26c
			cp[i-1]='n';
Packit Service a8c26c
		fp->type = tp;
Packit Service a8c26c
		nv_onattr(np,NV_RDONLY);
Packit Service a8c26c
		sfprintf(out," with default value \b%s\b.]",nv_getval(np));
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(strcmp(str,"other")==0)
Packit Service a8c26c
	{
Packit Service a8c26c
		Nambfun_t	*bp;
Packit Service a8c26c
		if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
Packit Service a8c26c
		{
Packit Service a8c26c
			for(i=0; i < bp->num; i++)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(nv_isattr(bp->bltins[i],NV_OPTGET))
Packit Service a8c26c
					sfprintf(out,"\b%s.%s\b(3), ",np->nvname,bp->bnames[i]);
Packit Service a8c26c
                        }
Packit Service a8c26c
		}
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	}
Packit Service a8c26c
	help = &dp->names[dp->ndisc];
Packit Service a8c26c
	sp = sfnew((Sfio_t*)0,buffer,sizeof(buffer),-1,SF_STRING|SF_WRITE);
Packit Service a8c26c
	sfprintf(out,"[+?\b%s\b defines the following fields:]{\n",np->nvname);
Packit Service a8c26c
	for(i=0; i < dp->numnodes; i++)
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(dp->nodes,i);
Packit Service a8c26c
		if(tp=nv_type(nq))
Packit Service a8c26c
		{
Packit Service a8c26c
			Namfun_t *pp = nv_hasdisc(nq,&type_disc);
Packit Service a8c26c
			sfprintf(out,"\t[+%s?%s.\n",nq->nvname,tp->nvname);
Packit Service a8c26c
			n = strlen(nq->nvname);
Packit Service a8c26c
			while((cp=nv_namptr(dp->nodes,i+1)->nvname) && memcmp(cp,nq->nvname,n)==0 && cp[n]=='.')
Packit Service a8c26c
				i++;
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			sfseek(sp,(Sfoff_t)0, SEEK_SET);
Packit Service a8c26c
			nv_attribute(nq,sp,(char*)0,1);
Packit Service a8c26c
			cp = 0;
Packit Service a8c26c
			if(!nv_isattr(nq,NV_REF))
Packit Service a8c26c
				cp = sh_fmtq(nv_getval(nq));
Packit Service a8c26c
			sfputc(sp,0);
Packit Service a8c26c
			for(n=strlen(buffer); n>0 && buffer[n-1]==' '; n--);
Packit Service a8c26c
			buffer[n] = 0;
Packit Service a8c26c
			if(cp)
Packit Service a8c26c
				sfprintf(out,"\t[+%s?%s, default value is %s.\n",nq->nvname,*buffer?buffer:"string",cp);
Packit Service a8c26c
			else
Packit Service a8c26c
				sfprintf(out,"\t[+%s?%s.\n",nq->nvname,*buffer?buffer:"string");
Packit Service a8c26c
		}
Packit Service a8c26c
		if(help[i])
Packit Service a8c26c
			sfprintf(out,"  %s.",help[i]);
Packit Service a8c26c
		sfputc(out,']');
Packit Service a8c26c
	}
Packit Service a8c26c
	sfprintf(out,"}\n");
Packit Service a8c26c
	if(dp->ndisc>0)
Packit Service a8c26c
	{
Packit Service a8c26c
		stakseek(offset);
Packit Service a8c26c
		stakputs(NV_CLASS);
Packit Service a8c26c
		stakputc('.');
Packit Service a8c26c
		stakputs(np->nvname);
Packit Service a8c26c
		stakputc('.');
Packit Service a8c26c
		n = staktell();
Packit Service a8c26c
		sfprintf(out,"[+?\b%s\b defines the following discipline functions:]{\n",np->nvname);
Packit Service a8c26c
		for(i=0; i < dp->ndisc; i++)
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputs(dp->names[i]);
Packit Service a8c26c
			stakputc(0);
Packit Service a8c26c
			cp = 0;
Packit Service a8c26c
			if((nq = nv_search(stakptr(offset),sh.fun_tree,0)) && nq->nvalue.cp)
Packit Service a8c26c
				cp = nq->nvalue.rp->help;
Packit Service a8c26c
			if(nq && nv_isattr(nq,NV_STATICF))
Packit Service a8c26c
				sfprintf(out,"\t[+%s?:static:%s]\n",dp->names[i],cp?cp:Empty);
Packit Service a8c26c
			else
Packit Service a8c26c
				sfprintf(out,"\t[+%s?%s]\n",dp->names[i],cp?cp:Empty);
Packit Service a8c26c
			if(cp)
Packit Service a8c26c
				sfputc(out,'.');
Packit Service a8c26c
			stakseek(n);
Packit Service a8c26c
		}
Packit Service a8c26c
		sfprintf(out,"}\n");
Packit Service a8c26c
	}
Packit Service a8c26c
	stakseek(offset);
Packit Service a8c26c
	sfclose(sp);
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static int std_disc(Namval_t *mp, Namtype_t *pp)
Packit Service a8c26c
{
Packit Service a8c26c
	register const char	*sp, *cp = strrchr(mp->nvname,'.');
Packit Service a8c26c
	register const char	**argv;
Packit Service a8c26c
	register int			i;
Packit Service a8c26c
	Namval_t		*np=0,*nq;
Packit Service a8c26c
	if(cp)
Packit Service a8c26c
		cp++;
Packit Service a8c26c
	else
Packit Service a8c26c
		cp = mp->nvname;
Packit Service a8c26c
	if(strcmp(cp,"create")==0)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(pp)
Packit Service a8c26c
			pp->cp = mp;
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	}
Packit Service a8c26c
	for(argv=nv_discnames; sp=*argv; argv++) 
Packit Service a8c26c
	{
Packit Service a8c26c
		if(strcmp(cp,sp)==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(!pp)
Packit Service a8c26c
				return(1);
Packit Service a8c26c
			goto found;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	return(0);
Packit Service a8c26c
found:
Packit Service a8c26c
	if(memcmp(sp=mp->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
Packit Service a8c26c
		sp += sizeof(NV_CLASS);
Packit Service a8c26c
	sp += strlen(pp->fun.type->nvname)+1;
Packit Service a8c26c
	if(sp == cp)
Packit Service a8c26c
		np = pp->fun.type;
Packit Service a8c26c
	else for(i=1; i < pp->numnodes; i++)
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(pp->nodes,i);
Packit Service a8c26c
		if(memcmp(nq->nvname, sp, cp-sp-1)==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			np = nq;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	if(np)
Packit Service a8c26c
	{
Packit Service a8c26c
		nv_onattr(mp,NV_NOFREE);
Packit Service a8c26c
		if(!nv_setdisc(np,cp, mp, (Namfun_t*)np))
Packit Service a8c26c
			sfprintf(sfstderr," nvsetdisc failed name=%s sp=%s cp=%s\n",np->nvname,sp,cp);
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
		sfprintf(sfstderr,"can't set discipline %s cp=%s \n",sp,cp);
Packit Service a8c26c
	return(1);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
void nv_addtype(Namval_t *np, const char *optstr, Optdisc_t *op, size_t optsz)
Packit Service a8c26c
{
Packit Service a8c26c
	Namdecl_t	*cp = newof((Namdecl_t*)0,Namdecl_t,1,optsz);
Packit Service a8c26c
	Optdisc_t	*dp = (Optdisc_t*)(cp+1);
Packit Service a8c26c
	Shell_t		*shp = sh_getinterp();
Packit Service a8c26c
	Namval_t	*mp,*bp;
Packit Service a8c26c
	char		*name;
Packit Service a8c26c
	if(optstr)
Packit Service a8c26c
		cp->optstring = optstr;
Packit Service a8c26c
	else
Packit Service a8c26c
		cp->optstring = sh_opttype;
Packit Service a8c26c
	memcpy((void*)dp,(void*)op, optsz);
Packit Service a8c26c
	cp->optinfof = (void*)dp;
Packit Service a8c26c
	cp->tp = np;
Packit Service a8c26c
	mp = nv_search("typeset",shp->bltin_tree,0);
Packit Service a8c26c
	if(name=strrchr(np->nvname,'.'))
Packit Service a8c26c
		name++;
Packit Service a8c26c
	else
Packit Service a8c26c
		name = np->nvname; 
Packit Service a8c26c
#if SHOPT_NAMESPACE
Packit Service a8c26c
	if(bp=(Namval_t*)shp->namespace)
Packit Service a8c26c
	{
Packit Service a8c26c
		Namtype_t *tp = (Namtype_t*)nv_hasdisc(np, &type_disc);
Packit Service a8c26c
		if(tp)
Packit Service a8c26c
			tp->nsp = bp;
Packit Service a8c26c
		if(!shp->strbuf2)
Packit Service a8c26c
			shp->strbuf2 = sfstropen();
Packit Service a8c26c
		sfprintf(shp->strbuf2,".%s.%s%c\n",nv_name(bp)+1,name,0);
Packit Service a8c26c
		name = sfstruse(shp->strbuf2);
Packit Service a8c26c
	}
Packit Service a8c26c
#endif /* SHOPT_NAMESPACE */
Packit Service a8c26c
	if((bp=nv_search(name,shp->fun_tree,NV_NOSCOPE)) && !bp->nvalue.ip)
Packit Service a8c26c
		nv_delete(bp,shp->fun_tree,0);
Packit Service a8c26c
	bp = sh_addbuiltin(name, (Shbltin_f)mp->nvalue.bfp, (void*)cp); 
Packit Service a8c26c
	nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
Packit Service a8c26c
	nv_onattr(np, NV_RDONLY);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
void nv_newtype(Namval_t *mp)
Packit Service a8c26c
{
Packit Service a8c26c
	struct	{
Packit Service a8c26c
		    Optdisc_t	opt;
Packit Service a8c26c
		    Namval_t	*np;
Packit Service a8c26c
		}	optdisc;
Packit Service a8c26c
	memset(&optdisc,0,sizeof(optdisc));
Packit Service a8c26c
	optdisc.opt.infof = typeinfo;
Packit Service a8c26c
	optdisc.np = mp;
Packit Service a8c26c
	nv_addtype(mp,sh_opttype, &optdisc.opt, sizeof(optdisc));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * This function creates a type out of the <numnodes> nodes in the
Packit Service a8c26c
 * array <nodes>.  The first node is the name for the type
Packit Service a8c26c
 */
Packit Service a8c26c
Namval_t *nv_mktype(Namval_t **nodes, int numnodes)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*mp=nodes[0], *bp=0, *np, *nq, **mnodes=nodes;
Packit Service a8c26c
	int		i,j,k,m,n,nd=0,nref=0,iref=0,inherit=0;
Packit Service a8c26c
	int		size=sizeof(NV_DATA), dsize=0, nnodes;
Packit Service a8c26c
	size_t		offset=0;
Packit Service a8c26c
	char		*name=0, *cp, *sp, **help;
Packit Service a8c26c
	Namtype_t	*pp,*qp=0,*dp,*tp;
Packit Service a8c26c
	Dt_t		*root = nv_dict(mp);
Packit Service a8c26c
	struct Namref	*nrp = 0;
Packit Service a8c26c
	Namfun_t	*fp;
Packit Service a8c26c
	m = strlen(mp->nvname)+1;
Packit Service a8c26c
	if(numnodes < 2)
Packit Service a8c26c
	{
Packit Service a8c26c
		cp = nodes[0]->nvname;
Packit Service a8c26c
		_nv_unset(nodes[0],NV_RDONLY);
Packit Service a8c26c
		errormsg(SH_DICT,ERROR_exit(1),e_badtypedef,cp);
Packit Service a8c26c
	}
Packit Service a8c26c
	for(nnodes=1,i=1; i 
Packit Service a8c26c
	{
Packit Service a8c26c
		np=nodes[i];
Packit Service a8c26c
		if(is_afunction(np))
Packit Service a8c26c
		{
Packit Service a8c26c
			if(!std_disc(np, (Namtype_t*)0))
Packit Service a8c26c
			{
Packit Service a8c26c
				size += strlen(np->nvname+m)+1;
Packit Service a8c26c
				if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
Packit Service a8c26c
					size -= sizeof(NV_CLASS);
Packit Service a8c26c
				nd++;
Packit Service a8c26c
			}
Packit Service a8c26c
			continue;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(nv_isattr(np,NV_REF))
Packit Service a8c26c
			iref++;
Packit Service a8c26c
		if(np->nvenv)
Packit Service a8c26c
			size += strlen((char*)np->nvenv)+1;
Packit Service a8c26c
		if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
Packit Service a8c26c
			continue;
Packit Service a8c26c
		if(qp)
Packit Service a8c26c
		{	/* delete duplicates */
Packit Service a8c26c
			for(j=0; j < qp->numnodes;j++)
Packit Service a8c26c
			{
Packit Service a8c26c
				nq = nv_namptr(qp->nodes,j);
Packit Service a8c26c
				if(strcmp(nq->nvname,&np->nvname[m])==0)
Packit Service a8c26c
					break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(j < qp->numnodes)
Packit Service a8c26c
				continue;
Packit Service a8c26c
		}
Packit Service a8c26c
		nnodes++;
Packit Service a8c26c
		if(name && memcmp(&name[m],&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
Packit Service a8c26c
			offset -= sizeof(char*);
Packit Service a8c26c
		dsize = nv_datasize(np,&offset);
Packit Service a8c26c
		if(!nv_isarray(np) && (dp=(Namtype_t*)nv_hasdisc(np, &type_disc)))
Packit Service a8c26c
		{
Packit Service a8c26c
			nnodes += dp->numnodes;
Packit Service a8c26c
			if((n=dp->strsize)<0)
Packit Service a8c26c
				n = -n;
Packit Service a8c26c
			iref = nref += dp->nref;
Packit Service a8c26c
			if(np->nvname[m]=='_' && np->nvname[m+1]==0 && (bp=nv_type(np)))
Packit Service a8c26c
			{
Packit Service a8c26c
				qp = dp;
Packit Service a8c26c
				nd = dp->ndisc;
Packit Service a8c26c
				nnodes = dp->numnodes;
Packit Service a8c26c
				offset = 0;
Packit Service a8c26c
				dsize = nv_size(np);
Packit Service a8c26c
				size += n;
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
				size += n + dp->numnodes*(strlen(&np->nvname[m])+1);
Packit Service a8c26c
			n = strlen(np->nvname);
Packit Service a8c26c
			while((i+1) < numnodes && (cp=nodes[i+1]->nvname) && memcmp(cp,np->nvname,n)==0 && cp[n]=='.')
Packit Service a8c26c
				i++;
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(nv_isattr(np,NV_REF))
Packit Service a8c26c
			nref++;
Packit Service a8c26c
		offset += (dsize?dsize:4);
Packit Service a8c26c
		size += (n=strlen(name=np->nvname)-m+1);
Packit Service a8c26c
	}
Packit Service a8c26c
	offset = roundof(offset,sizeof(char*));
Packit Service a8c26c
	nv_setsize(mp,offset);
Packit Service a8c26c
	if(nd)
Packit Service a8c26c
		nd++;
Packit Service a8c26c
	k = roundof(sizeof(Namtype_t),sizeof(Sfdouble_t)) - sizeof(Namtype_t);
Packit Service a8c26c
	pp = newof(NiL, Namtype_t, 1, nnodes*NV_MINSZ + offset + size + (nnodes+nd)*sizeof(char*) + iref*sizeof(struct Namref)+k);
Packit Service a8c26c
	pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +offset+k;
Packit Service a8c26c
	pp->fun.type = mp;
Packit Service a8c26c
	pp->parent = nv_lastdict();
Packit Service a8c26c
	pp->np = mp;
Packit Service a8c26c
	pp->bp = bp;
Packit Service a8c26c
	pp->childfun.fun.disc = &chtype_disc;
Packit Service a8c26c
	pp->childfun.fun.nofree = 1;
Packit Service a8c26c
	pp->childfun.ttype = pp;
Packit Service a8c26c
	pp->childfun.ptype = pp;
Packit Service a8c26c
	pp->fun.disc = &type_disc;
Packit Service a8c26c
	pp->nodes = (char*)(pp+1);
Packit Service a8c26c
	pp->numnodes = nnodes;
Packit Service a8c26c
	pp->data = pp->nodes + nnodes*NV_MINSZ +k;
Packit Service a8c26c
	pp->dsize = offset;
Packit Service a8c26c
	nrp = (struct Namref*)(pp->data+offset);
Packit Service a8c26c
	pp->names = (char**)(nrp+iref);
Packit Service a8c26c
	help = &pp->names[nd];
Packit Service a8c26c
	pp->strsize = size;
Packit Service a8c26c
	cp = (char*)&pp->names[nd+nnodes];
Packit Service a8c26c
	if(qp)
Packit Service a8c26c
		mnodes = newof(NiL, Namval_t*, nd+1, 0);
Packit Service a8c26c
	nd = 0;
Packit Service a8c26c
	nq = nv_namptr(pp->nodes,0);
Packit Service a8c26c
	nq->nvname = cp;
Packit Service a8c26c
	nv_onattr(nq,NV_MINIMAL);
Packit Service a8c26c
	cp = strcopy(cp,NV_DATA);
Packit Service a8c26c
	*cp++ = 0;
Packit Service a8c26c
	for(name=0, offset=0, k=i=1; i < numnodes; i++)
Packit Service a8c26c
	{
Packit Service a8c26c
		np=nodes[i];
Packit Service a8c26c
		if(is_afunction(np))
Packit Service a8c26c
		{
Packit Service a8c26c
			sp = np->nvname+m;
Packit Service a8c26c
			if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
Packit Service a8c26c
				sp += sizeof(NV_CLASS);
Packit Service a8c26c
			if(!std_disc(np, pp))
Packit Service a8c26c
			{
Packit Service a8c26c
				/* see if discipline already defined */
Packit Service a8c26c
				for(j=0; j< nd; j++)
Packit Service a8c26c
				{
Packit Service a8c26c
					if(strcmp(sp,pp->names[j])==0)
Packit Service a8c26c
					{
Packit Service a8c26c
						mnodes[j] = nodes[i];
Packit Service a8c26c
						break;
Packit Service a8c26c
					}
Packit Service a8c26c
				}
Packit Service a8c26c
				if(j>=nd)
Packit Service a8c26c
				{
Packit Service a8c26c
					pp->names[nd] = cp;
Packit Service a8c26c
					mnodes[nd++] = nodes[i];
Packit Service a8c26c
					cp = strcopy(cp,sp);
Packit Service a8c26c
					*cp++ = 0;
Packit Service a8c26c
				}
Packit Service a8c26c
				nv_onattr(mnodes[j],NV_NOFREE);
Packit Service a8c26c
			}
Packit Service a8c26c
			continue;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(inherit)
Packit Service a8c26c
		{
Packit Service a8c26c
			for(j=0; j < k ; j++)
Packit Service a8c26c
			{
Packit Service a8c26c
				nq = nv_namptr(pp->nodes,j);
Packit Service a8c26c
				if(strcmp(nq->nvname,&np->nvname[m])==0)
Packit Service a8c26c
					break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(j < k)
Packit Service a8c26c
			{
Packit Service a8c26c
				sp = nv_getval(np);
Packit Service a8c26c
				if(nv_isvtree(np))
Packit Service a8c26c
					sfprintf(sfstderr,"initialization not implemented\n");
Packit Service a8c26c
				else if(sp) 
Packit Service a8c26c
					nv_putval(nq,sp,0);
Packit Service a8c26c
				goto skip;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
Packit Service a8c26c
		{
Packit Service a8c26c
			char *val=nv_getval(np);
Packit Service a8c26c
			nq = nv_namptr(pp->nodes,0);
Packit Service a8c26c
			nq->nvfun = 0;
Packit Service a8c26c
			nv_putval(nq,(val?val:0),nv_isattr(np,~(NV_IMPORT|NV_EXPORT|NV_ARRAY)));
Packit Service a8c26c
			nq->nvflag = np->nvflag|NV_NOFREE|NV_MINIMAL;
Packit Service a8c26c
			goto skip;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(qp)
Packit Service a8c26c
		{
Packit Service a8c26c
			Nambfun_t	*bp;
Packit Service a8c26c
			dp = (Namtype_t*)nv_hasdisc(nv_type(np), &type_disc);
Packit Service a8c26c
			memcpy(pp->nodes,dp->nodes,dp->numnodes*NV_MINSZ);
Packit Service a8c26c
			offset = nv_size(np);
Packit Service a8c26c
			memcpy(pp->data,dp->data,offset);
Packit Service a8c26c
			for(k=0;k < dp->numnodes; k++)
Packit Service a8c26c
			{
Packit Service a8c26c
				Namval_t *nr = nv_namptr(qp->nodes,k);
Packit Service a8c26c
				nq = nv_namptr(pp->nodes,k);
Packit Service a8c26c
				if(fixnode(pp,dp,k,nrp,0))
Packit Service a8c26c
				{
Packit Service a8c26c
					nrp++;
Packit Service a8c26c
					nq = nq->nvalue.nrp->np;
Packit Service a8c26c
				}
Packit Service a8c26c
				if(!nv_isattr(nr,NV_REF) && !nv_hasdisc(nr,&type_disc))
Packit Service a8c26c
				{
Packit Service a8c26c
					if(nr->nvsize)
Packit Service a8c26c
						memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size=nv_datasize(nr,(size_t*)0));
Packit Service a8c26c
					else
Packit Service a8c26c
					{
Packit Service a8c26c
						nq->nvalue.cp = nr->nvalue.cp;
Packit Service a8c26c
						nv_onattr(nq,NV_NOFREE);
Packit Service a8c26c
					}
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
Packit Service a8c26c
			{
Packit Service a8c26c
				for(j=0; j < bp->num; j++)
Packit Service a8c26c
				{
Packit Service a8c26c
					pp->names[nd++] = (char*)bp->bnames[j];
Packit Service a8c26c
					mnodes[j] = bp->bltins[j];
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			qp = 0;
Packit Service a8c26c
			inherit=1;
Packit Service a8c26c
			goto skip;
Packit Service a8c26c
		}
Packit Service a8c26c
		nq = nv_namptr(pp->nodes,k);
Packit Service a8c26c
		if(np->nvenv)
Packit Service a8c26c
		{
Packit Service a8c26c
			/* need to save the string pointer */
Packit Service a8c26c
			nv_offattr(np,NV_EXPORT);
Packit Service a8c26c
			help[k] = cp;
Packit Service a8c26c
			cp = strcopy(cp,np->nvenv);
Packit Service a8c26c
			j = *help[k];
Packit Service a8c26c
			if(islower(j))
Packit Service a8c26c
				*help[k] = toupper(j);
Packit Service a8c26c
			*cp++ = 0;
Packit Service a8c26c
			np->nvenv = 0;
Packit Service a8c26c
		}
Packit Service a8c26c
		nq->nvname = cp;
Packit Service a8c26c
		if(name && memcmp(name,&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
Packit Service a8c26c
			offset -= sizeof(char*);
Packit Service a8c26c
		dsize = nv_datasize(np,&offset);
Packit Service a8c26c
		cp = strcopy(name=cp, &np->nvname[m]);
Packit Service a8c26c
		n = cp-name;
Packit Service a8c26c
		*cp++ = 0;
Packit Service a8c26c
		nq->nvsize = np->nvsize;
Packit Service a8c26c
		nq->nvflag = (np->nvflag&~(NV_IMPORT|NV_EXPORT))|NV_NOFREE|NV_MINIMAL;
Packit Service a8c26c
		if(dp = (Namtype_t*)nv_hasdisc(np, &type_disc))
Packit Service a8c26c
		{
Packit Service a8c26c
			int r,kfirst=k;
Packit Service a8c26c
			char *cname = &np->nvname[m];
Packit Service a8c26c
			/*
Packit Service a8c26c
			 * If field is a type, mark the type by setting
Packit Service a8c26c
			 * strsize<0.  This changes create_type()
Packit Service a8c26c
			 */
Packit Service a8c26c
			clone_all_disc(np,nq,NV_RDONLY);
Packit Service a8c26c
			if(nv_isarray(np))
Packit Service a8c26c
			{
Packit Service a8c26c
				nv_disc(nq, &pp->childfun.fun, NV_LAST);
Packit Service a8c26c
				k++;
Packit Service a8c26c
				goto skip;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(fp=nv_hasdisc(nq,&chtype_disc))
Packit Service a8c26c
				nv_disc(nq, &pp->childfun.fun, NV_LAST);
Packit Service a8c26c
			if(tp = (Namtype_t*)nv_hasdisc(nq, &type_disc))
Packit Service a8c26c
				tp->strsize = -tp->strsize;
Packit Service a8c26c
else sfprintf(sfstderr,"tp==NULL\n");
Packit Service a8c26c
			for(r=0; r < dp->numnodes; r++)
Packit Service a8c26c
			{
Packit Service a8c26c
				Namval_t *nr = nv_namptr(dp->nodes,r);
Packit Service a8c26c
				nq = nv_namptr(pp->nodes,++k);
Packit Service a8c26c
				nq->nvname = cp;
Packit Service a8c26c
				dsize = nv_datasize(nr,&offset);
Packit Service a8c26c
				nq->nvflag = nr->nvflag;
Packit Service a8c26c
				if(nr->nvalue.cp)
Packit Service a8c26c
				{
Packit Service a8c26c
					Namchld_t *xp = (Namchld_t*)nv_hasdisc(nr,&chtype_disc);
Packit Service a8c26c
					if(xp && nr->nvalue.cp >= xp->ptype->data && nr->nvalue.cp < xp->ptype->data+xp->ptype->fun.dsize)
Packit Service a8c26c
					{
Packit Service a8c26c
						nq->nvalue.cp = pp->data+offset;
Packit Service a8c26c
						memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,dsize);
Packit Service a8c26c
						nv_onattr(nq,NV_NOFREE);
Packit Service a8c26c
					}
Packit Service a8c26c
					else
Packit Service a8c26c
						nq->nvalue.cp = strdup(nr->nvalue.cp);
Packit Service a8c26c
					nv_disc(nq, &pp->childfun.fun, NV_LAST);
Packit Service a8c26c
				}
Packit Service a8c26c
				nq->nvsize = nr->nvsize;
Packit Service a8c26c
				offset += dsize;
Packit Service a8c26c
				if(*cname!='_' || cname[1])
Packit Service a8c26c
				{
Packit Service a8c26c
					cp = strcopy(cp,cname);
Packit Service a8c26c
					*cp++ = '.';
Packit Service a8c26c
				}
Packit Service a8c26c
				cp = strcopy(cp,nr->nvname);
Packit Service a8c26c
				*cp++ = 0;
Packit Service a8c26c
			}
Packit Service a8c26c
			while((i+1) < numnodes && (cname=&nodes[i+1]->nvname[m]) && memcmp(cname,&np->nvname[m],n)==0 && cname[n]=='.')
Packit Service a8c26c
			{
Packit Service a8c26c
				int j=kfirst;
Packit Service a8c26c
				nv_unset(np);
Packit Service a8c26c
				nv_delete(np,root,0);
Packit Service a8c26c
				np = nodes[++i];
Packit Service a8c26c
				while(j < k)
Packit Service a8c26c
				{
Packit Service a8c26c
					nq = nv_namptr(pp->nodes,++j);
Packit Service a8c26c
					if(strcmp(nq->nvname,cname)==0)
Packit Service a8c26c
					{
Packit Service a8c26c
						sfprintf(sfstderr,"%s found at k=%d\n",nq->nvname,k);
Packit Service a8c26c
						if(nq->nvalue.cp>=pp->data && nq->nvalue.cp< (char*)pp->names)
Packit Service a8c26c
							memcpy((char*)nq->nvalue.cp,np->nvalue.cp,nv_datasize(np,0));
Packit Service a8c26c
						break;
Packit Service a8c26c
					}
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			Namarr_t *ap;
Packit Service a8c26c
			j = nv_isattr(np,NV_NOFREE);
Packit Service a8c26c
			if(j==0 && (ap=nv_arrayptr(np)) && !ap->fun)
Packit Service a8c26c
				j = 1;
Packit Service a8c26c
			nq->nvfun = np->nvfun;
Packit Service a8c26c
			np->nvfun = 0;
Packit Service a8c26c
			nv_disc(nq, &pp->childfun.fun, NV_LAST);
Packit Service a8c26c
			if(nq->nvfun)
Packit Service a8c26c
			{
Packit Service a8c26c
				for(fp=nq->nvfun; fp; fp = fp->next)
Packit Service a8c26c
					fp->nofree |= 1;
Packit Service a8c26c
			}
Packit Service a8c26c
			nq->nvalue.cp = np->nvalue.cp;
Packit Service a8c26c
			if(dsize  && (np->nvalue.cp || !nv_isarray(np)))
Packit Service a8c26c
			{
Packit Service a8c26c
				nq->nvalue.cp = pp->data+offset;
Packit Service a8c26c
				sp = (char*)np->nvalue.cp;
Packit Service a8c26c
				if(nv_isattr(np,NV_INT16P) ==NV_INT16)
Packit Service a8c26c
				{
Packit Service a8c26c
					sp= (char*)&np->nvalue;
Packit Service a8c26c
					nv_onattr(nq,NV_INT16P);
Packit Service a8c26c
					j = 1;
Packit Service a8c26c
				}
Packit Service a8c26c
				if(sp)
Packit Service a8c26c
					memcpy((char*)nq->nvalue.cp,sp,dsize);
Packit Service a8c26c
				else if(nv_isattr(np,NV_LJUST|NV_RJUST))
Packit Service a8c26c
					memset((char*)nq->nvalue.cp,' ',dsize);
Packit Service a8c26c
				if(!j)
Packit Service a8c26c
					free((void*)np->nvalue.cp);
Packit Service a8c26c
			}
Packit Service a8c26c
			if(!nq->nvalue.cp && nq->nvfun== &pp->childfun.fun)
Packit Service a8c26c
				nq->nvalue.cp = Empty;
Packit Service a8c26c
			np->nvalue.cp = 0;
Packit Service a8c26c
#if 0
Packit Service a8c26c
			offset += dsize;
Packit Service a8c26c
#else
Packit Service a8c26c
			offset += (dsize?dsize:4);
Packit Service a8c26c
#endif
Packit Service a8c26c
		}
Packit Service a8c26c
		k++;
Packit Service a8c26c
	skip:
Packit Service a8c26c
		if(!nv_isnull(np))
Packit Service a8c26c
			_nv_unset(np,0);
Packit Service a8c26c
		nv_delete(np,root,0);
Packit Service a8c26c
	}
Packit Service a8c26c
	pp->ndisc = nd;
Packit Service a8c26c
	pp->nref = nref;
Packit Service a8c26c
	if(k>1)
Packit Service a8c26c
	{
Packit Service a8c26c
		nv_setsize(mp,offset);
Packit Service a8c26c
		mp->nvalue.cp = pp->data;
Packit Service a8c26c
		nv_onattr(mp,NV_NOFREE|NV_BINARY|NV_RAW);
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(!mp->nvalue.cp)
Packit Service a8c26c
		mp->nvalue.cp = Empty;
Packit Service a8c26c
	nv_onattr(mp,NV_TAGGED);
Packit Service a8c26c
	nv_disc(mp, &pp->fun, NV_LAST);
Packit Service a8c26c
	if(nd>0)
Packit Service a8c26c
	{
Packit Service a8c26c
		pp->names[nd] = 0;
Packit Service a8c26c
		nv_adddisc(mp, (const char**)pp->names, mnodes);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(mnodes!=nodes)
Packit Service a8c26c
		free((void*)mnodes);
Packit Service a8c26c
	nv_newtype(mp);
Packit Service a8c26c
	return(mp);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Namval_t *nv_mkinttype(char *name, size_t size, int sign, const char *help, Namdisc_t *ep)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*mp;
Packit Service a8c26c
	Namfun_t	*fp;
Packit Service a8c26c
	Namdisc_t	*dp;
Packit Service a8c26c
	int		offset=staktell();
Packit Service a8c26c
	stakputs(NV_CLASS);
Packit Service a8c26c
	stakputc('.');
Packit Service a8c26c
	stakputs(name);
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
        mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
Packit Service a8c26c
	stakseek(offset);
Packit Service a8c26c
	offset = size + sizeof(Namdisc_t);
Packit Service a8c26c
	fp = newof(NiL, Namfun_t, 1, offset);
Packit Service a8c26c
	fp->type = mp;
Packit Service a8c26c
	fp->nofree |= 1;
Packit Service a8c26c
	fp->dsize = sizeof(Namfun_t)+size;
Packit Service a8c26c
	dp = (Namdisc_t*)(fp+1);
Packit Service a8c26c
	if(ep)
Packit Service a8c26c
		*dp = *ep;
Packit Service a8c26c
	dp->clonef =  clone_inttype;
Packit Service a8c26c
	fp->disc = dp;
Packit Service a8c26c
	mp->nvalue.cp = (char*)(fp+1) + sizeof(Namdisc_t);
Packit Service a8c26c
	nv_setsize(mp,10);
Packit Service a8c26c
	mp->nvenv = (char*)help;
Packit Service a8c26c
	nv_onattr(mp,NV_NOFREE|NV_RDONLY|NV_INTEGER|NV_EXPORT);
Packit Service a8c26c
	if(size==16)
Packit Service a8c26c
		nv_onattr(mp,NV_INT16P);
Packit Service a8c26c
	else if(size==64)
Packit Service a8c26c
		nv_onattr(mp,NV_INT64);
Packit Service a8c26c
	if(!sign)
Packit Service a8c26c
		nv_onattr(mp,NV_UNSIGN);
Packit Service a8c26c
	nv_disc(mp, fp, NV_LAST);
Packit Service a8c26c
	nv_newtype(mp);
Packit Service a8c26c
	return(mp);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
void nv_typename(Namval_t *tp, Sfio_t *out)
Packit Service a8c26c
{
Packit Service a8c26c
	char *v,*cp;
Packit Service a8c26c
	Namtype_t	*dp;
Packit Service a8c26c
	cp = nv_name(tp);
Packit Service a8c26c
	if(v=strrchr(cp,'.'))
Packit Service a8c26c
		cp = v+1;
Packit Service a8c26c
	if((dp = (Namtype_t*)nv_hasdisc(tp,&type_disc)) && dp->bp)
Packit Service a8c26c
	{
Packit Service a8c26c
		nv_typename(dp->bp,out);
Packit Service a8c26c
		sfprintf(out,"%s.%s",sfstruse(out),cp);
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
		sfputr(out,cp,-1);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
Namval_t *nv_type(Namval_t *np)
Packit Service a8c26c
{
Packit Service a8c26c
	Namfun_t  *fp;
Packit Service a8c26c
	if(nv_isattr(np,NV_BLTIN|BLT_DCL)==(NV_BLTIN|BLT_DCL))
Packit Service a8c26c
	{
Packit Service a8c26c
		Namdecl_t *ntp = (Namdecl_t*)nv_context(np);
Packit Service a8c26c
		return(ntp?ntp->tp:0);
Packit Service a8c26c
	}
Packit Service a8c26c
	for(fp=np->nvfun; fp; fp=fp->next)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(fp->type)
Packit Service a8c26c
			return(fp->type);
Packit Service a8c26c
		if(fp->disc && fp->disc->typef && (np= (*fp->disc->typef)(np,fp)))
Packit Service a8c26c
			return(np);
Packit Service a8c26c
	}
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * call any and all create functions
Packit Service a8c26c
 */
Packit Service a8c26c
static void type_init(Namval_t *np)
Packit Service a8c26c
{
Packit Service a8c26c
	int 		i;
Packit Service a8c26c
	Namtype_t	*dp, *pp=(Namtype_t*)nv_hasdisc(np,&type_disc);
Packit Service a8c26c
	Namval_t	*nq;
Packit Service a8c26c
	if(!pp)
Packit Service a8c26c
		return;
Packit Service a8c26c
	for(i=0; i < pp->numnodes; i++)
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(pp->nodes,i);
Packit Service a8c26c
		if((dp=(Namtype_t*)nv_hasdisc(nq,&type_disc)) && dp->cp)
Packit Service a8c26c
			sh_fun(dp->cp,nq, (char**)0);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(pp->cp)
Packit Service a8c26c
		sh_fun(pp->cp, np, (char**)0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * This function turns variable <np>  to the type <tp>
Packit Service a8c26c
 */
Packit Service a8c26c
int nv_settype(Namval_t* np, Namval_t *tp, int flags)
Packit Service a8c26c
{
Packit Service a8c26c
	int		isnull = nv_isnull(np);
Packit Service a8c26c
	int		rdonly = nv_isattr(np,NV_RDONLY);
Packit Service a8c26c
	char		*val=0;
Packit Service a8c26c
	Namarr_t	*ap=0;
Packit Service a8c26c
	Shell_t		*shp = sh_getinterp();
Packit Service a8c26c
	int		nelem=0,subshell=shp->subshell;
Packit Service a8c26c
#if SHOPT_TYPEDEF
Packit Service a8c26c
	Namval_t	*tq;
Packit Service a8c26c
	if(nv_type(np)==tp)
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	if(nv_isarray(np) && (tq=nv_type(np)))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(tp==tq)
Packit Service a8c26c
			return(0);
Packit Service a8c26c
		errormsg(SH_DICT,ERROR_exit(1),e_redef,nv_name(np));
Packit Service a8c26c
	}
Packit Service a8c26c
	if((ap=nv_arrayptr(np)) && ap->nelem>0)
Packit Service a8c26c
	{
Packit Service a8c26c
		nv_putsub(np,NIL(char*),ARRAY_SCAN);
Packit Service a8c26c
		ap->hdr.type = tp;
Packit Service a8c26c
		do
Packit Service a8c26c
		{
Packit Service a8c26c
			nv_arraysettype(np, tp, nv_getsub(np),flags);
Packit Service a8c26c
		}
Packit Service a8c26c
		while(nv_nextsub(np));
Packit Service a8c26c
	}
Packit Service a8c26c
	else if(ap || nv_isarray(np))
Packit Service a8c26c
	{
Packit Service a8c26c
		flags &= ~NV_APPEND;
Packit Service a8c26c
		if(!ap)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(subshell)
Packit Service a8c26c
			{
Packit Service a8c26c
				sh_assignok(np,1);
Packit Service a8c26c
				shp->subshell = 0;
Packit Service a8c26c
			}
Packit Service a8c26c
			nv_putsub(np,"0",ARRAY_FILL);
Packit Service a8c26c
			ap = nv_arrayptr(np);
Packit Service a8c26c
			nelem = 1;
Packit Service a8c26c
		
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
#endif /*SHOPT_TYPEDEF */
Packit Service a8c26c
	{
Packit Service a8c26c
		if(isnull)
Packit Service a8c26c
			flags &= ~NV_APPEND;
Packit Service a8c26c
		else if(!nv_isvtree(np))
Packit Service a8c26c
		{
Packit Service a8c26c
			val = strdup(nv_getval(np));
Packit Service a8c26c
			if(!(flags&NV_APPEND))
Packit Service a8c26c
				_nv_unset(np, NV_RDONLY);
Packit Service a8c26c
		}
Packit Service a8c26c
		if(!nv_clone(tp,np,flags|NV_NOFREE))
Packit Service a8c26c
			return(0);
Packit Service a8c26c
	}
Packit Service a8c26c
	if(ap)
Packit Service a8c26c
	{
Packit Service a8c26c
		int nofree;
Packit Service a8c26c
		nv_disc(np,&ap->hdr,NV_POP);
Packit Service a8c26c
		np->nvalue.up = 0;
Packit Service a8c26c
		nv_clone(tp,np,flags|NV_NOFREE);
Packit Service a8c26c
		if(np->nvalue.cp && np->nvalue.cp!=Empty && !nv_isattr(np,NV_NOFREE))
Packit Service a8c26c
			free((void*)np->nvalue.cp);
Packit Service a8c26c
		np->nvalue.up = 0;
Packit Service a8c26c
		nofree = ap->hdr.nofree;
Packit Service a8c26c
		ap->hdr.nofree = 0;
Packit Service a8c26c
		ap->hdr.type = tp;
Packit Service a8c26c
		nv_disc(np, &ap->hdr, NV_FIRST);
Packit Service a8c26c
		ap->hdr.nofree = nofree;
Packit Service a8c26c
		nv_onattr(np,NV_ARRAY);
Packit Service a8c26c
		if(nelem)
Packit Service a8c26c
		{
Packit Service a8c26c
			ap->nelem++;
Packit Service a8c26c
			nv_putsub(np,"0",0);
Packit Service a8c26c
			_nv_unset(np,NV_RDONLY|NV_TYPE);
Packit Service a8c26c
			ap->nelem--;
Packit Service a8c26c
			shp->subshell = subshell;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	type_init(np);
Packit Service a8c26c
	if(!rdonly)
Packit Service a8c26c
		nv_offattr(np,NV_RDONLY);
Packit Service a8c26c
	if(val)
Packit Service a8c26c
	{
Packit Service a8c26c
		nv_putval(np,val,NV_RDONLY);
Packit Service a8c26c
		free((void*)val);
Packit Service a8c26c
	}
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#define S(x)	#x
Packit Service a8c26c
#define FIELD(x,y)	{ S(y##x),	S(x##_t), offsetof(struct stat,st_##y##x) }
Packit Service a8c26c
typedef struct _field_
Packit Service a8c26c
{
Packit Service a8c26c
	char	*name;
Packit Service a8c26c
	char	*type;
Packit Service a8c26c
	int	offset;
Packit Service a8c26c
} Fields_t;
Packit Service a8c26c
Packit Service a8c26c
Fields_t foo[]=
Packit Service a8c26c
{
Packit Service a8c26c
	FIELD(dev,),
Packit Service a8c26c
	FIELD(ino,),
Packit Service a8c26c
	FIELD(nlink,),
Packit Service a8c26c
	FIELD(mode,),
Packit Service a8c26c
	FIELD(uid,),
Packit Service a8c26c
	FIELD(gid,),
Packit Service a8c26c
	FIELD(size,),
Packit Service a8c26c
	FIELD(time,a),
Packit Service a8c26c
	FIELD(time,m),
Packit Service a8c26c
	FIELD(time,c),
Packit Service a8c26c
#if 0
Packit Service a8c26c
	FIELD(blksize,),
Packit Service a8c26c
	FIELD(blocks,),
Packit Service a8c26c
#endif
Packit Service a8c26c
	0
Packit Service a8c26c
}; 
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
Namval_t *nv_mkstruct(const char *name, int rsize, Fields_t *fields) 
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	*mp, *nq, *nr, *tp;
Packit Service a8c26c
	Fields_t	*fp;
Packit Service a8c26c
	Namtype_t	*dp, *pp;
Packit Service a8c26c
	char		*cp, *sp;
Packit Service a8c26c
	int		nnodes=0, offset=staktell(), n, r, i, j;
Packit Service a8c26c
	size_t		m, size=0;
Packit Service a8c26c
	stakputs(NV_CLASS);
Packit Service a8c26c
	stakputc('.');
Packit Service a8c26c
	r = staktell();
Packit Service a8c26c
	stakputs(name);
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
Packit Service a8c26c
	stakseek(r);
Packit Service a8c26c
Packit Service a8c26c
	for(fp=fields; fp->name; fp++)
Packit Service a8c26c
	{
Packit Service a8c26c
		m = strlen(fp->name)+1;
Packit Service a8c26c
		size += m;
Packit Service a8c26c
		nnodes++;
Packit Service a8c26c
		if(memcmp(fp->type,"typeset",7))
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputs(fp->type);
Packit Service a8c26c
			stakputc(0);
Packit Service a8c26c
			tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
Packit Service a8c26c
			stakseek(r);
Packit Service a8c26c
			if(!tp)
Packit Service a8c26c
				errormsg(SH_DICT,ERROR_exit(1),e_unknowntype,strlen(fp->type),fp->type);
Packit Service a8c26c
			if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
Packit Service a8c26c
			{
Packit Service a8c26c
				nnodes += dp->numnodes;
Packit Service a8c26c
				if((i=dp->strsize) < 0)
Packit Service a8c26c
					i = -i;
Packit Service a8c26c
				size += i + dp->numnodes*m;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	pp = newof(NiL,Namtype_t, 1,  nnodes*NV_MINSZ + rsize + size);
Packit Service a8c26c
	pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +rsize;
Packit Service a8c26c
	pp->fun.type = mp;
Packit Service a8c26c
	pp->np = mp;
Packit Service a8c26c
	pp->childfun.fun.disc = &chtype_disc;
Packit Service a8c26c
	pp->childfun.fun.nofree = 1;
Packit Service a8c26c
	pp->childfun.ttype = pp;
Packit Service a8c26c
	pp->childfun.ptype = pp;
Packit Service a8c26c
	pp->fun.disc = &type_disc;
Packit Service a8c26c
	pp->nodes = (char*)(pp+1);
Packit Service a8c26c
	pp->numnodes = nnodes;
Packit Service a8c26c
	pp->strsize = size;
Packit Service a8c26c
	pp->data = pp->nodes + nnodes*NV_MINSZ;
Packit Service a8c26c
	cp = pp->data + rsize;
Packit Service a8c26c
	for(i=0,fp=fields; fp->name; fp++)
Packit Service a8c26c
	{
Packit Service a8c26c
		nq = nv_namptr(pp->nodes,i++);
Packit Service a8c26c
		nq->nvname = cp;
Packit Service a8c26c
		nq->nvalue.cp = pp->data + fp->offset;
Packit Service a8c26c
		nv_onattr(nq,NV_MINIMAL|NV_NOFREE);
Packit Service a8c26c
		m = strlen(fp->name)+1;
Packit Service a8c26c
		memcpy(cp, fp->name, m);
Packit Service a8c26c
		cp += m;
Packit Service a8c26c
		if(memcmp(fp->type,"typeset",7))
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputs(fp->type);
Packit Service a8c26c
			stakputc(0);
Packit Service a8c26c
			tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
Packit Service a8c26c
			stakseek(r);
Packit Service a8c26c
			clone_all_disc(tp,nq,NV_RDONLY);
Packit Service a8c26c
			nq->nvflag = tp->nvflag|NV_MINIMAL|NV_NOFREE;
Packit Service a8c26c
			nq->nvsize = tp->nvsize;
Packit Service a8c26c
			if(dp = (Namtype_t*)nv_hasdisc(nq,&type_disc))
Packit Service a8c26c
				dp->strsize = -dp->strsize;
Packit Service a8c26c
			if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
Packit Service a8c26c
			{
Packit Service a8c26c
				if(nv_hasdisc(nq,&chtype_disc))
Packit Service a8c26c
					nv_disc(nq, &pp->childfun.fun, NV_LAST);
Packit Service a8c26c
				sp = (char*)nq->nvalue.cp;
Packit Service a8c26c
				memcpy(sp, dp->data, nv_size(tp));
Packit Service a8c26c
				for(j=0; j < dp->numnodes; j++)
Packit Service a8c26c
				{
Packit Service a8c26c
					nr = nv_namptr(dp->nodes,j);
Packit Service a8c26c
					nq = nv_namptr(pp->nodes,i++);
Packit Service a8c26c
					nq->nvname = cp;
Packit Service a8c26c
					memcpy(cp,fp->name,m);
Packit Service a8c26c
					cp[m-1] = '.';
Packit Service a8c26c
					cp += m;
Packit Service a8c26c
					n = strlen(nr->nvname)+1;
Packit Service a8c26c
					memcpy(cp,nr->nvname,n);
Packit Service a8c26c
					cp += n;
Packit Service a8c26c
					if(nr->nvalue.cp>=dp->data && nr->nvalue.cp < (char*)pp + pp->fun.dsize)
Packit Service a8c26c
					{
Packit Service a8c26c
						nq->nvalue.cp = sp + (nr->nvalue.cp-dp->data);
Packit Service a8c26c
					}
Packit Service a8c26c
					nq->nvflag = nr->nvflag;
Packit Service a8c26c
					nq->nvsize = nr->nvsize;
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		else if(strmatch(fp->type+7,"*-*i*")==0)
Packit Service a8c26c
		{
Packit Service a8c26c
			nv_onattr(nq,NV_NOFREE|NV_RDONLY|NV_INTEGER);
Packit Service a8c26c
			if(strmatch(fp->type+7,"*-*s*")==0)
Packit Service a8c26c
				nv_onattr(nq,NV_INT16P);
Packit Service a8c26c
			else if(strmatch(fp->type+7,"*-*l*")==0)
Packit Service a8c26c
				nv_onattr(nq,NV_INT64);
Packit Service a8c26c
			if(strmatch(fp->type+7,"*-*u*")==0)
Packit Service a8c26c
				nv_onattr(nq,NV_UNSIGN);
Packit Service a8c26c
		}
Packit Service a8c26c
		
Packit Service a8c26c
	}
Packit Service a8c26c
	stakseek(offset);
Packit Service a8c26c
	nv_onattr(mp,NV_RDONLY|NV_NOFREE|NV_BINARY);
Packit Service a8c26c
	nv_setsize(mp,rsize);
Packit Service a8c26c
	nv_disc(mp, &pp->fun, NV_LAST);
Packit Service a8c26c
	mp->nvalue.cp = pp->data;
Packit Service a8c26c
	nv_newtype(mp);
Packit Service a8c26c
	return(mp);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static void put_stat(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
Packit Service a8c26c
{
Packit Service a8c26c
	if(val)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(stat(val,(struct stat*)np->nvalue.cp)<0)
Packit Service a8c26c
			sfprintf(sfstderr,"stat of %s failed\n",val);
Packit Service a8c26c
		return;
Packit Service a8c26c
	}
Packit Service a8c26c
	nv_putv(np,val,flag,nfp);
Packit Service a8c26c
	nv_disc(np,nfp,NV_POP);
Packit Service a8c26c
	if(!(nfp->nofree&1))
Packit Service a8c26c
		free((void*)nfp);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static const Namdisc_t stat_disc =
Packit Service a8c26c
{
Packit Service a8c26c
        0,
Packit Service a8c26c
        put_stat
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
void nv_mkstat(void)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t *tp;
Packit Service a8c26c
	Namfun_t *fp;
Packit Service a8c26c
	tp = nv_mkstruct("stat_t", sizeof(struct stat), foo);
Packit Service a8c26c
	nv_offattr(tp,NV_RDONLY);
Packit Service a8c26c
	nv_setvtree(tp);
Packit Service a8c26c
	fp = newof(NiL,Namfun_t,1,0);
Packit Service a8c26c
	fp->type = tp;
Packit Service a8c26c
	fp->disc = &stat_disc;
Packit Service a8c26c
	nv_disc(tp,fp,NV_FIRST);
Packit Service a8c26c
	nv_putval(tp,e_devnull,0);
Packit Service a8c26c
	nv_onattr(tp,NV_RDONLY);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static void write_indent(Sfio_t *out,char *str,int n,int indent)
Packit Service a8c26c
{
Packit Service a8c26c
	register int	c, first=1;
Packit Service a8c26c
	register char	*cp = str;
Packit Service a8c26c
	while(n-- && (c = *str++))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(c=='\n')
Packit Service a8c26c
		{
Packit Service a8c26c
			if(!first)
Packit Service a8c26c
				sfnputc(out,'\t',indent);
Packit Service a8c26c
			first = 0;
Packit Service a8c26c
			sfwrite(out,cp,str-cp);
Packit Service a8c26c
			cp = str;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	if(cp > str)
Packit Service a8c26c
	{
Packit Service a8c26c
		sfnputc(out,'\t',indent);
Packit Service a8c26c
		sfwrite(out,cp,str-cp);
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
int	sh_outtype(Shell_t *shp,Sfio_t *out)
Packit Service a8c26c
{
Packit Service a8c26c
	Namval_t	node,*mp,*tp;
Packit Service a8c26c
	Dt_t		*dp;
Packit Service a8c26c
	char		*cp,*sp,*xp,nvtype[sizeof(NV_CLASS)];
Packit Service a8c26c
	Sfio_t		*iop=0;
Packit Service a8c26c
	int		n=0,indent = 0;
Packit Service a8c26c
	if(cp=shp->prefix)
Packit Service a8c26c
	{
Packit Service a8c26c
		indent=1;
Packit Service a8c26c
		while(*cp)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(*cp++ =='.')
Packit Service a8c26c
				indent++;
Packit Service a8c26c
		}
Packit Service a8c26c
		n = cp-shp->prefix+1;
Packit Service a8c26c
	}
Packit Service a8c26c
	strcpy(nvtype,NV_CLASS);
Packit Service a8c26c
	if(!(mp = nv_open(nvtype, shp->var_base,NV_NOADD|NV_VARNAME)))
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	memcpy(&node,L_ARGNOD,sizeof(node));
Packit Service a8c26c
	L_ARGNOD->nvfun = 0;
Packit Service a8c26c
	L_ARGNOD->nvalue.cp = 0;
Packit Service a8c26c
	dp  = 	nv_dict(mp);
Packit Service a8c26c
	if(indent==0)
Packit Service a8c26c
	for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(!nv_search(tp->nvname,shp->bltin_tree,0))
Packit Service a8c26c
			continue;
Packit Service a8c26c
		sfprintf(out,"typeset -T %s\n",tp->nvname);
Packit Service a8c26c
	}
Packit Service a8c26c
	for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(nv_isnull(tp))
Packit Service a8c26c
			continue;
Packit Service a8c26c
		if(indent && (memcmp(tp->nvname,shp->prefix,n-1) || tp->nvname[n-1]!='.' || strchr(tp->nvname+n,'.')))
Packit Service a8c26c
			continue;
Packit Service a8c26c
		nv_settype(L_ARGNOD,tp,0);
Packit Service a8c26c
		if(indent)
Packit Service a8c26c
			sfnputc(out,'\t',indent);
Packit Service a8c26c
		sfprintf(out,"typeset -T %s=",tp->nvname+n);
Packit Service a8c26c
		shp->last_table = 0;
Packit Service a8c26c
		cp = nv_getval(L_ARGNOD);
Packit Service a8c26c
		if(indent)
Packit Service a8c26c
			write_indent(out,cp,strlen(cp)-1,indent);
Packit Service a8c26c
		else
Packit Service a8c26c
			sfprintf(out,"%.*s",strlen(cp)-1,cp);
Packit Service a8c26c
		_nv_unset(L_ARGNOD,NV_RDONLY);
Packit Service a8c26c
		for(sp=0; sp=nv_setdisc(tp,(char*)0,(Namval_t*)sp,(Namfun_t*)tp);)
Packit Service a8c26c
		{
Packit Service a8c26c
			mp = (Namval_t*)nv_setdisc(tp,sp,tp,(Namfun_t*)tp);
Packit Service a8c26c
			if(!mp || mp==tp)
Packit Service a8c26c
				continue;
Packit Service a8c26c
			if(cp=strrchr(mp->nvname,'.'))
Packit Service a8c26c
				cp++;
Packit Service a8c26c
			else
Packit Service a8c26c
				cp = mp->nvname;
Packit Service a8c26c
			if(indent)
Packit Service a8c26c
				sfnputc(out,'\t',indent);
Packit Service a8c26c
			if(nv_isattr(mp,NV_FPOSIX))
Packit Service a8c26c
				sfprintf(out,"\t%s()",cp);
Packit Service a8c26c
			else
Packit Service a8c26c
				sfprintf(out,"\tfunction %s",cp);
Packit Service a8c26c
			xp = 0;
Packit Service a8c26c
			if(mp->nvalue.ip && mp->nvalue.rp->hoffset>=0)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(nv_isattr(mp,NV_FTMP))
Packit Service a8c26c
					iop = shp->heredocs;
Packit Service a8c26c
				else if(xp=mp->nvalue.rp->fname)
Packit Service a8c26c
					iop = sfopen(iop,xp,"r");
Packit Service a8c26c
				else if(shp->gd->hist_ptr)
Packit Service a8c26c
					iop = (shp->gd->hist_ptr)->histfp;
Packit Service a8c26c
				if(iop && sfseek(iop,(Sfoff_t)mp->nvalue.rp->hoffset,SEEK_SET)>=0)
Packit Service a8c26c
					sfmove(iop,out, nv_size(mp), -1);
Packit Service a8c26c
				else
Packit Service a8c26c
					sfputc(iop,'\n');
Packit Service a8c26c
				if(xp)
Packit Service a8c26c
					sfclose(iop);
Packit Service a8c26c
				if(nv_isattr(mp,NV_STATICF|NV_TAGGED))
Packit Service a8c26c
				{
Packit Service a8c26c
					if(indent)
Packit Service a8c26c
						sfnputc(out,'\t',indent);
Packit Service a8c26c
					sfwrite(out,"\ttypeset -f",11);
Packit Service a8c26c
					if(nv_isattr(mp,NV_STATICF))
Packit Service a8c26c
						sfputc(out,'S');
Packit Service a8c26c
					if(nv_isattr(mp,NV_TAGGED))
Packit Service a8c26c
						sfputc(out,'t');
Packit Service a8c26c
					if(mp->nvalue.rp->help)
Packit Service a8c26c
						sfprintf(out,"h '%s'",mp->nvalue.rp->help);
Packit Service a8c26c
					sfprintf(out," %s\n",cp);
Packit Service a8c26c
				}
Packit Service a8c26c
				iop = 0;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		if(indent)
Packit Service a8c26c
			sfnputc(out,'\t',indent);
Packit Service a8c26c
		sfwrite(out,")\n",2);
Packit Service a8c26c
	}
Packit Service a8c26c
	dtdelete(shp->var_base,L_ARGNOD);
Packit Service a8c26c
	memcpy(L_ARGNOD,&node,sizeof(node));
Packit Service a8c26c
	dtinsert(shp->var_base,L_ARGNOD);
Packit Service a8c26c
	return(0);
Packit Service a8c26c
}