da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Routines to implement a stack-like storage library
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
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 *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is a rewrite of the stk library that uses sfio
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * dgk@research.att.com
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sfio_t.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <align.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stk.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * A stack is a header and a linked list of frames
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The first frame has structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Sfio_t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Sfdisc_t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * struct stk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Frames have structure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * struct frame
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * data
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STK_ALIGN ALIGN_BOUND
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STK_FSIZE (1024*sizeof(int))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STK_HDRSIZE (sizeof(Sfio_t)+sizeof(Sfdisc_t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef char* (*_stk_overflow_)(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int stkexcept(Sfio_t*,int,void*,Sfdisc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Sfdisc_t stkdisc = { 0, 0, 0, stkexcept };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t _Stak_data = SFNEW((char*)0,0,-1,SF_STATIC|SF_WRITE|SF_STRING,&stkdisc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin__EXTERN__(Sfio_t, _Stak_data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct frame
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *prev; /* address of previous frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *end; /* address of end this frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char **aliases; /* address aliases */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int nalias; /* number of aliases */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct stk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _stk_overflow_ stkoverflow; /* called when malloc fails */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short stkref; /* reference count; */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short stkflags; /* stack attributes */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *stkbase; /* beginning of current stack frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *stkend; /* end of current stack frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int init; /* 1 when initialized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct stk *stkcur; /* pointer to current stk */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *stkgrow(Sfio_t*, unsigned);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define stream2stk(stream) ((stream)==stkstd? stkcur:\
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((struct stk*)(((char*)(stream))+STK_HDRSIZE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define stk2stream(sp) ((Sfio_t*)(((char*)(sp))-STK_HDRSIZE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define stkleft(stream) ((stream)->_endb-(stream)->_data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef STKSTATS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int create;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int delete;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int install;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int alloc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int copy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int puts;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int seek;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int set;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int grow;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int addsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int delsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int movsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } _stkstats;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define increment(x) (_stkstats.x++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define count(x,n) (_stkstats.x += (n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define increment(x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define count(x,n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* STKSTATS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char Omsg[] = "malloc failed while growing stack\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * default overflow exception
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *overflow(int n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin write(2,Omsg, sizeof(Omsg)-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin exit(2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTREACHED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize stkstd, sfio operations may have already occcured
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void stkinit(int size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Sfio_t *sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin init = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = stkopen(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin init = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinstall(sp,overflow);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int stkexcept(register Sfio_t *stream, int type, void* val, Sfdisc_t* dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(dp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(val);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_CLOSING:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp = sp->stkbase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct frame *fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(--sp->stkref<=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(delete);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stream==stkstd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkset(stream,(char*)0,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp = (struct frame*)cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fp->prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = fp->prev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(fp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(fp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = stream->_next = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_FINAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_DPOP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_WRITE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_SEEK:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long size = sfvalue(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t *old = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stream!=stkstd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = stkinstall(stream,NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!stkgrow(stkstd,size-(stkstd->_endb-stkstd->_data)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(old)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinstall(old,NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(size);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_NEW:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create a stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t *stkopen(int flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int bsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Sfio_t *stream;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct frame *fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Sfdisc_t *dp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(stream=newof((char*)0,Sfio_t, 1, sizeof(*dp)+sizeof(*sp))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(create);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count(addsize,sizeof(*stream)+sizeof(*dp)+sizeof(*sp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp = (Sfdisc_t*)(stream+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp->exceptf = stkexcept;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = (struct stk*)(dp+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkref = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkflags = (flags&STK_SMALL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flags&STK_NULL) sp->stkoverflow = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else sp->stkoverflow = stkcur?stkcur->stkoverflow:overflow;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bsize = init+sizeof(struct frame);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef USE_REALLOC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flags&STK_SMALL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bsize = roundof(bsize,STK_FSIZE/16);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bsize = roundof(bsize,STK_FSIZE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bsize -= sizeof(struct frame);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(fp=newof((char*)0,struct frame, 1,bsize)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count(addsize,sizeof(*fp)+bsize);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = (char*)(fp+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkbase = (char*)fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->prev = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->nalias = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->aliases = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->end = sp->stkend = cp+bsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sfnew(stream,cp,bsize,-1,SF_STRING|SF_WRITE|SF_STATIC|SF_EOF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((Sfio_t*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfdisc(stream,dp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t *stkinstall(Sfio_t *stream, _stk_overflow_ oflow)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t *old;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(oflow)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkcur->stkoverflow = oflow;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((Sfio_t*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(install);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = stkcur?stk2stream(stkcur):0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stream)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(sfstack(stkstd, SF_POPSTACK));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stream!=stkstd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfstack(stkstd,stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkcur = sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef USE_REALLOC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*** someday ***/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = stkcur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(oflow)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkoverflow = oflow;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * increase the reference count on the given <stack>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint stklink(register Sfio_t* stream)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sp->stkref++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint stkclose(Sfio_t* stream)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->stkref>1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkref--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sfclose(stream));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin/*
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * returns 1 if <loc> is on this stack
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint stkon(register Sfio_t * stream, register char* loc)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct stk *sp = stream2stk(stream);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct frame *fp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(fp=(struct frame*)sp->stkbase; fp; fp=(struct frame*)fp->prev)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(loc>=((char*)(fp+1)) && loc< fp->end)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkset(register Sfio_t * stream, register char* loc, unsigned offset)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct frame *fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int frames = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(offset+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(set);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp = (struct frame*)sp->stkbase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = sp->stkbase + roundof(sizeof(struct frame), STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = fp->nalias;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n-->0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(loc==fp->aliases[n])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin loc = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether <loc> is in current stack frame */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(loc>=cp && loc<=sp->stkend)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(frames)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(stream,cp,sp->stkend-cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = (unsigned char*)(cp + roundof(loc-cp,STK_ALIGN));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_next = (unsigned char*)loc+offset;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto found;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fp->prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkbase = fp->prev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkend = ((struct frame*)(fp->prev))->end;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)fp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin frames++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set stack back to the beginning */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = (char*)(fp+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(frames)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(stream,cp,sp->stkend-cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = stream->_next = (unsigned char*)cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinfound:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)stream->_data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allocate <n> bytes on the current stack
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkalloc(register Sfio_t *stream, register unsigned int n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *old;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(alloc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = roundof(n,STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stkleft(stream) <= (int)n && !stkgrow(stream,n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = stream->_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = stream->_next = old+n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * begin a new stack word of at least <n> bytes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *_stkseek(register Sfio_t *stream, register unsigned n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(seek);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stkleft(stream) <= (int)n && !stkgrow(stream,n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_next = stream->_data+n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)stream->_data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * advance the stack to the current top
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if extra is non-zero, first add a extra bytes and zero the first
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkfreeze(register Sfio_t *stream, register unsigned extra)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *old, *top;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(extra);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = stream->_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin top = stream->_next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(extra)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(extra > (stream->_endb-stream->_next))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(top = (unsigned char*)stkgrow(stream,extra)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = stream->_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *top = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin top += extra;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_next = stream->_data += roundof(top-old,STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)old);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * copy string <str> onto the stack as a new stack word
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinchar *stkcopy(Sfio_t *stream, const char* str)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *cp = (unsigned char*)str;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int off=stktell(stream);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin char buff[40], *tp=buff;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(off)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(off > sizeof(buff))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(tp = malloc(off)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct stk *sp = stream2stk(stream);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!sp->stkoverflow || !(tp = (*sp->stkoverflow)(off)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy(tp, stream->_data, off);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*cp++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = roundof(cp-(unsigned char*)str,STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stkinit(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(copy);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stkleft(stream) <= n && !stkgrow(stream,n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy((char*)(cp=stream->_data),str);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stream->_data = stream->_next = cp+n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(off)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin _stkseek(stream,off);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy(stream->_data, tp, off);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(tp!=buff)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin free((void*)tp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *stkgrow(register Sfio_t *stream, unsigned size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct stk *sp = stream2stk(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct frame *fp= (struct frame*)sp->stkbase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp, *dp=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned m = stktell(stream);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int nn=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n += (m + sizeof(struct frame)+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sp->stkflags&STK_SMALL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef USE_REALLOC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = roundof(n,STK_FSIZE/16);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* !USE_REALLOC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = roundof(n,STK_FSIZE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether current frame can be extended */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stkptr(stream,0)==sp->stkbase+sizeof(struct frame))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nn = fp->nalias+1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp=sp->stkbase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkbase = ((struct frame*)dp)->prev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = newof(dp, char, n, nn*sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp && (!sp->stkoverflow || !(cp = (*sp->stkoverflow)(n))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin increment(grow);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count(addsize,n - (dp?m:0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(dp && cp==dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nn--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp = (struct frame*)cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->prev = sp->stkbase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkbase = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp->stkend = fp->end = cp+n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = (char*)(fp+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = sp->stkbase + roundof((cp-sp->stkbase),STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fp->nalias=nn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->aliases = (char**)fp->end;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp->aliases[nn-1] = dp + roundof(sizeof(struct frame),STK_ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(m && !dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(cp,(char*)stream->_data,m);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count(movsize,m);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(stream,cp,sp->stkend-cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((char*)(stream->_next = stream->_data+m));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}