da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Routines to implement a stack-like storage library
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * A stack consists of a link list of variable size frames
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The beginning of each frame is initialized with a frame structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * that contains a pointer to the previous frame and a pointer to the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * end of the current frame.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is a rewrite of the stk library that uses sfio
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * dgk@research.att.com
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * A stack is a header and a linked list of frames
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The first frame has structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Sfdisc_t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * struct stk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Frames have structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * struct frame
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t _Stak_data = SFNEW((char*)0,0,-1,SF_STATIC|SF_WRITE|SF_STRING,&stkdisc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _stk_overflow_ stkoverflow; /* called when malloc fails */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define stk2stream(sp) ((Sfio_t*)(((char*)(sp))-STK_HDRSIZE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define stkleft(stream) ((stream)->_endb-(stream)->_data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* STKSTATS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char Omsg[] = "malloc failed while growing stack\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * default overflow exception
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTREACHED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize stkstd, sfio operations may have already occcured
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int stkexcept(register Sfio_t *stream, int type, void* val, Sfdisc_t* dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!stkgrow(stkstd,size-(stkstd->_endb-stkstd->_data)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create a stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(stream=newof((char*)0,Sfio_t, 1, sizeof(*dp)+sizeof(*sp))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count(addsize,sizeof(*stream)+sizeof(*dp)+sizeof(*sp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else sp->stkoverflow = stkcur?stkcur->stkoverflow:overflow;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sfnew(stream,cp,bsize,-1,SF_STRING|SF_WRITE|SF_STATIC|SF_EOF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((Sfio_t*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a pointer to the current stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <stream> is not null, it becomes the new current stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <oflow> becomes the new overflow function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t *stkinstall(Sfio_t *stream, _stk_overflow_ oflow)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((Sfio_t*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*** someday ***/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * increase the reference count on the given <stack>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * terminate a stack and free up the space
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * >0 returned if reference decremented but still > 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 0 returned on last close
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <0 returned on error
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * returns 1 if <loc> is on this stack
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint stkon(register Sfio_t * stream, register char* loc)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(fp=(struct frame*)sp->stkbase; fp; fp=(struct frame*)fp->prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * reset the bottom of the current stack back to <loc>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <loc> is not in this stack, then the stack is reset to the beginning
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * otherwise, the top of the stack is set to stkbot+<offset>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkset(register Sfio_t * stream, register char* loc, unsigned offset)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = sp->stkbase + roundof(sizeof(struct frame), STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n-->0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether <loc> is in current stack frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = (unsigned char*)(cp + roundof(loc-cp,STK_ALIGN));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set stack back to the beginning */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allocate <n> bytes on the current stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkalloc(register Sfio_t *stream, register unsigned int n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * begin a new stack word of at least <n> bytes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *_stkseek(register Sfio_t *stream, register unsigned n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * advance the stack to the current top
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if extra is non-zero, first add a extra bytes and zero the first
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkfreeze(register Sfio_t *stream, register unsigned extra)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_next = stream->_data += roundof(top-old,STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * copy string <str> onto the stack as a new stack word
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!sp->stkoverflow || !(tp = (*sp->stkoverflow)(off)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*cp++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * add a new stack frame of size >= <n> to the current stack.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <n> > 0, copy the bytes from stkbot to stktop to the new stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <n> is zero, then copy the remainder of the stack frame from stkbot
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * to the end is copied into the new stack frame
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *stkgrow(register Sfio_t *stream, unsigned size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* !USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether current frame can be extended */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp && (!sp->stkoverflow || !(cp = (*sp->stkoverflow)(n))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = sp->stkbase + roundof((cp-sp->stkbase),STK_ALIGN);