2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: stk.c /main/2 1996/05/08 19:45:44 drk $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
47 /* : : generated by proto : : */
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__ "C"
57 #define __PROTO__(x) x
59 #define __PARAM__(n,o) n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
72 #define __PROTO__(x) ()
73 #define __OTORP__(x) x
74 #define __PARAM__(n,o) o
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__ ...
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a) va_start(p,a)
90 #define __VA_START__(p,a) va_start(p)
98 * A stack is a header and a linked list of frames
99 * The first frame has structure
103 * Frames have structure
107 #define STK_FSIZE (1024*sizeof(int))
108 #define STK_HDRSIZE (sizeof(Sfio_t)+sizeof(Sfdisc_t))
110 typedef char* (*_stk_overflow_) __PROTO__((int));
112 static int stkexcept __PROTO__((Sfio_t*,int,Sfdisc_t*));
113 static Sfdisc_t stkdisc = { 0, 0, 0, stkexcept };
115 #if _DLL_INDIRECT_DATA && !_DLL
116 static Sfio_t _Stk_data_data =
121 SFNEW((char*)0,0,-1,SF_STATIC|SF_WRITE|SF_STRING,&stkdisc);
123 #if _DLL_INDIRECT_DATA && !_DLL
124 Sfio_t _Stk_data = &_Stk_data_data;
129 char *prev; /* address of previous frame */
130 char *end; /* address of end this frame */
135 _stk_overflow_ stkoverflow; /* called when malloc fails */
136 short stkref; /* reference count; */
137 short stkflags; /* stack attributes */
138 char *stkbase; /* beginning of current stack frame */
139 char *stkend; /* end of current stack frame */
142 static int init; /* 1 when initialized */
143 static struct stk *stkcur; /* pointer to current stk */
144 static char *stkgrow __PROTO__((Sfio_t*, unsigned));
146 #define stream2stk(stream) ((stream)==stkstd? stkcur:\
147 ((struct stk*)(((char*)(stream))+STK_HDRSIZE)))
148 #define stk2stream(sp) ((Sfio_t*)(((char*)(sp))-STK_HDRSIZE))
149 #define stkleft(stream) ((stream)->endb-(stream)->data)
168 # define increment(x) (_stkstats.x++)
169 # define count(x,n) (_stkstats.x += (n))
171 # define increment(x)
173 #endif /* STKSTATS */
175 static const char Omsg[] = "malloc failed while growing stack\n";
178 * default overflow exception
180 static char *overflow __PARAM__((int n), (n)) __OTORP__(int n;){
182 write(2,Omsg, sizeof(Omsg)-1);
189 * initialize stkstd, sfio operations may have already occcured
191 static void stkinit __PARAM__((int size), (size)) __OTORP__(int size;){
196 stkinstall(sp,overflow);
199 static int stkexcept __PARAM__((register Sfio_t *stream, int type, Sfdisc_t* dp), (stream, type, dp)) __OTORP__(register Sfio_t *stream; int type; Sfdisc_t* dp;){
204 return(stkclose(stream));
211 old = stkinstall(stream,NiL);
212 stkgrow(stkstd,sfslen()-(stkstd->endb-stkstd->data));
228 Sfio_t *stkopen __PARAM__((int flags), (flags)) __OTORP__(int flags;){
230 register Sfio_t *stream;
231 register struct stk *sp;
232 register struct frame *fp;
233 register Sfdisc_t *dp;
235 if(!(stream=newof((char*)0,Sfio_t, 1, sizeof(*dp)+sizeof(*sp))))
238 count(addsize,sizeof(*stream)+sizeof(*dp)+sizeof(*sp));
239 dp = (Sfdisc_t*)(stream+1);
240 dp->exceptf = stkexcept;
241 sp = (struct stk*)(dp+1);
243 sp->stkflags = (flags&STK_SMALL);
244 sp->stkoverflow = stkcur?stkcur->stkoverflow:overflow;
245 bsize = init+sizeof(struct frame);
248 bsize = roundof(bsize,STK_FSIZE/16);
250 #endif /* USE_REALLOC */
251 bsize = roundof(bsize,STK_FSIZE);
252 bsize -= sizeof(struct frame);
253 if(!(fp=newof((char*)0,struct frame, 1,bsize)))
258 count(addsize,sizeof(*fp)+bsize);
260 sp->stkbase = (char*)fp;
262 fp->end = sp->stkend = cp+bsize;
263 if(!sfnew(stream,cp,bsize,-1,SF_STRING|SF_WRITE|SF_STATIC|SF_EOF))
270 * return a pointer to the current stack
271 * if <stream> is not null, it becomes the new current stack
272 * <oflow> becomes the new overflow function
274 Sfio_t *stkinstall __PARAM__((Sfio_t *stream, _stk_overflow_ oflow), (stream, oflow)) __OTORP__(Sfio_t *stream; _stk_overflow_ oflow;){
276 register struct stk *sp;
281 stkcur->stkoverflow = oflow;
285 old = stkcur?stk2stream(stkcur):0;
288 sp = stream2stk(stream);
289 while(sfstack(stkstd, SF_POPSTACK));
291 sfstack(stkstd,stream);
295 #endif /* USE_REALLOC */
300 sp->stkoverflow = oflow;
305 * increase the reference count on the given <stack>
307 int stklink __PARAM__((register Sfio_t* stream), (stream)) __OTORP__(register Sfio_t* stream;){
308 register struct stk *sp = stream2stk(stream);
309 return(sp->stkref++);
313 * terminate a stack and free up the space
315 int stkclose __PARAM__((Sfio_t* stream), (stream)) __OTORP__(Sfio_t* stream;){
316 register struct stk *sp = stream2stk(stream);
317 register char *cp = sp->stkbase;
318 register struct frame *fp;
323 stkset(stream,(char*)0,0);
326 fp = (struct frame*)cp;
342 * reset the bottom of the current stack back to <loc>
343 * if <loc> is not in this stack, then the stack is reset to the beginning
344 * otherwise, the top of the stack is set to stkbot+<offset>
347 char *stkset __PARAM__((register Sfio_t * stream, register char* loc, unsigned offset), (stream, loc, offset)) __OTORP__(register Sfio_t * stream; register char* loc; unsigned offset;){
348 register struct stk *sp = stream2stk(stream);
350 register struct frame *fp;
351 register int frames = 0;
357 /* see whether <loc> is in current stack frame */
358 if(loc>=(cp=sp->stkbase) && loc<=sp->stkend)
360 cp += sizeof(struct frame);
362 sfsetbuf(stream,cp,sp->stkend-cp);
363 stream->data = (unsigned char*)(cp + roundof(loc-cp,sizeof(char*)));
364 stream->next = (unsigned char*)loc+offset;
367 fp = (struct frame*)cp;
370 sp->stkbase = fp->prev;
371 sp->stkend = ((struct frame*)(fp->prev))->end;
378 /* set stack back to the beginning */
381 sfsetbuf(stream,cp,sp->stkend-cp);
383 stream->data = stream->next = (unsigned char*)cp;
385 return((char*)stream->data);
389 * allocate <n> bytes on the current stack
391 char *stkalloc __PARAM__((register Sfio_t *stream, register unsigned int n), (stream, n)) __OTORP__(register Sfio_t *stream; register unsigned int n;){
392 register unsigned char *old;
396 n = roundof(n,sizeof(char*));
397 if(stkleft(stream) <= (int)n)
400 stream->data = stream->next = old+n;
405 * begin a new stack word of at least <n> bytes
407 char *_stkseek __PARAM__((register Sfio_t *stream, register unsigned n), (stream, n)) __OTORP__(register Sfio_t *stream; register unsigned n;){
411 if(stkleft(stream) <= (int)n)
413 stream->next = stream->data+n;
414 return((char*)stream->data);
418 * advance the stack to the current top
419 * if extra is non-zero, first add a extra bytes and zero the first
421 char *stkfreeze __PARAM__((register Sfio_t *stream, register unsigned extra), (stream, extra)) __OTORP__(register Sfio_t *stream; register unsigned extra;){
422 register unsigned char *old, *top;
429 if(extra > (stream->endb-stream->next))
431 top = (unsigned char*)stkgrow(stream,extra);
437 stream->next = stream->data += roundof(top-old,sizeof(char*));
442 * copy string <str> onto the stack as a new stack word
444 char *stkcopy __PARAM__((Sfio_t *stream, const char* str), (stream, str)) __OTORP__(Sfio_t *stream; const char* str;){
445 register unsigned char *cp = (unsigned char*)str;
448 n = roundof(cp-(unsigned char*)str,sizeof(char*));
452 if(stkleft(stream) <= n)
454 strcpy((char*)(cp=stream->data),str);
455 stream->data = stream->next = cp+n;
460 * add a new stack frame of size >= <n> to the current stack.
461 * if <n> > 0, copy the bytes from stkbot to stktop to the new stack
462 * if <n> is zero, then copy the remainder of the stack frame from stkbot
463 * to the end is copied into the new stack frame
466 static char *stkgrow __PARAM__((register Sfio_t *stream, unsigned size), (stream, size)) __OTORP__(register Sfio_t *stream; unsigned size;){
467 register int n = size;
468 register struct stk *sp = stream2stk(stream);
469 register struct frame *fp;
471 register unsigned m = stktell(stream);
472 register int reused = 0;
473 n += (m + sizeof(struct frame)+1);
474 if(sp->stkflags&STK_SMALL)
476 n = roundof(n,STK_FSIZE/16);
478 #endif /* !USE_REALLOC */
479 n = roundof(n,STK_FSIZE);
480 /* see whether current frame can be extended */
481 if((char*)(stream->data) == sp->stkbase+sizeof(struct frame))
483 cp = newof(sp->stkbase,char,n,0);
487 cp = newof((char*)0, char, n, 0);
488 if(!cp) cp = (*sp->stkoverflow)(n);
491 fp = (struct frame*)cp;
494 fp->prev = sp->stkbase;
497 sp->stkend = fp->end = cp+n;
500 memcpy(cp,(char*)stream->data,m);
502 sfsetbuf(stream,cp,sp->stkend-cp);
503 return((char*)(stream->next = stream->data+m));