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: stak.c /main/3 1995/11/01 18:05:08 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF *
29 * AT&T BELL LABORATORIES *
30 * AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN *
31 * ACCORDANCE WITH APPLICABLE AGREEMENTS *
33 * Copyright (c) 1994 AT&T Bell Laboratories *
34 * Unpublished & Not for Publication *
35 * All Rights Reserved *
37 * The copyright notice above does not evidence any *
38 * actual or intended publication of such source code *
40 * This software was created by the *
41 * Software Engineering Research Department *
42 * AT&T Bell Laboratories *
44 * For further information contact *
45 * advsoft@research.att.com *
46 * Randy Hackbarth 908-582-5245 *
47 * Dave Belanger 908-582-7427 *
49 ***************************************************************/
51 /* : : generated by proto : : */
55 #if !defined(__PROTO__)
56 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
57 #if defined(__cplusplus)
58 #define __MANGLE__ "C"
63 #define __PROTO__(x) x
65 #define __PARAM__(n,o) n
66 #if !defined(__STDC__) && !defined(__cplusplus)
67 #if !defined(c_plusplus)
78 #define __PROTO__(x) ()
79 #define __OTORP__(x) x
80 #define __PARAM__(n,o) o
88 #if defined(__cplusplus) || defined(c_plusplus)
89 #define __VARARG__ ...
93 #if defined(__STDARG__)
94 #define __VA_START__(p,a) va_start(p,a)
96 #define __VA_START__(p,a) va_start(p)
106 * A stack is a header and a linked list of frames
107 * The first frame has structure
111 * Frames have structure
115 #define STAK_FSIZE (1024*sizeof(int))
116 #define STAK_HDRSIZE (sizeof(Sfile_t)+sizeof(Sfdisc_t))
118 typedef char* (*_stak_overflow_) __PROTO__((int));
120 static int stakexcept __PROTO__((Sfile_t*,int,Sfdisc_t*));
121 static Sfdisc_t stakdisc = { 0, 0, 0, stakexcept };
122 Sfile_t _Stak_data=SFNEW((char*)0,0,-1,SF_STATIC|SF_WRITE|SF_STRING,&stakdisc);
126 char *prev; /* address of previous frame */
127 char *end; /* address of end this frame */
132 _stak_overflow_ stakoverflow; /* called when malloc fails */
133 short stakref; /* reference count; */
134 short stakflags; /* stack attributes */
135 char *stakbase; /* beginning of current stack frame */
136 char *stakend; /* end of current stack frame */
139 static int init; /* 1 when initialized */
140 static struct stak *stakcur; /* pointer to current stak */
141 static char *stakgrow __PROTO__((unsigned));
143 #define stream2stak(stream) ((struct stak*)(((char*)(stream))+STAK_HDRSIZE))
144 #define stak2stream(sp) ((Sfile_t*)(((char*)(sp))-STAK_HDRSIZE))
145 #define stakleft() (staksp->endb-staksp->data)
164 # define increment(x) (_stakstats.x++)
165 # define count(x,n) (_stakstats.x += (n))
167 # define increment(x)
169 #endif /* STAKSTATS */
171 static const char Omsg[] = "malloc failed while growing stack\n";
174 * default overflow exception
176 static char *overflow __PARAM__((int n), (n)) __OTORP__(int n;)
180 write(2,Omsg, sizeof(Omsg)-1);
187 * initialize staksp, sfio operations may have already occcured
189 static void stakinit __PARAM__((int size), (size)) __OTORP__(int size;)
192 register Sfile_t *sp;
196 stakinstall(sp,overflow);
199 static int stakexcept __PARAM__((Sfile_t* sp, int type, Sfdisc_t* dp), (sp, type, dp)) __OTORP__(Sfile_t* sp; int type; Sfdisc_t* dp;)
206 return(stakdelete(sp));
213 old = stakinstall(sp,NiL);
214 stakgrow(sfslen()-(staksp->endb-staksp->data));
216 stakinstall(old,NiL);
230 Sfile_t *stakcreate __PARAM__((int flags), (flags)) __OTORP__(int flags;)
234 register Sfile_t *stream;
235 register struct stak *sp;
236 register struct frame *fp;
237 register Sfdisc_t *dp;
239 if(!(stream=newof((char*)0,Sfile_t, 1, sizeof(*dp)+sizeof(*sp))))
242 count(addsize,sizeof(*stream)+sizeof(*dp)+sizeof(*sp));
243 dp = (Sfdisc_t*)(stream+1);
244 dp->exceptf = stakexcept;
245 sp = (struct stak*)(dp+1);
247 sp->stakflags = (flags&STAK_SMALL);
248 sp->stakoverflow = stakcur?stakcur->stakoverflow:overflow;
249 bsize = init+sizeof(struct frame);
252 bsize = roundof(bsize,STAK_FSIZE/16);
254 #endif /* USE_REALLOC */
255 bsize = roundof(bsize,STAK_FSIZE);
256 bsize -= sizeof(struct frame);
257 if(!(fp=newof((char*)0,struct frame, 1,bsize)))
262 count(addsize,sizeof(*fp)+bsize);
264 sp->stakbase = (char*)fp;
266 fp->end = sp->stakend = cp+bsize;
267 if(!sfnew(stream,cp,bsize,-1,SF_STRING|SF_WRITE|SF_STATIC|SF_EOF))
274 * return a pointer to the current stack
275 * if <stream> is not null, it becomes the new current stack
276 * <oflow> becomes the new overflow function
278 Sfile_t *stakinstall __PARAM__((Sfile_t *stream, _stak_overflow_ oflow), (stream, oflow)) __OTORP__(Sfile_t *stream; _stak_overflow_ oflow;)
282 register struct stak *sp;
287 stakcur->stakoverflow = oflow;
291 old = stakcur?stak2stream(stakcur):0;
294 sp = stream2stak(stream);
295 while(sfstack(staksp, SF_POPSTACK));
297 sfstack(staksp,stream);
301 #endif /* USE_REALLOC */
306 sp->stakoverflow = oflow;
311 * increase the reference count on the given <stack>
313 int staklink __PARAM__((register Sfile_t* stream), (stream)) __OTORP__(register Sfile_t* stream;)
316 register struct stak *sp = stream2stak(stream);
317 return(sp->stakref++);
321 * terminate a stack and free up the space
323 int stakdelete __PARAM__((Sfile_t* stream), (stream)) __OTORP__(Sfile_t* stream;)
326 register struct stak *sp = stream2stak(stream);
327 register char *cp = sp->stakbase;
328 register struct frame *fp;
336 fp = (struct frame*)cp;
352 * reset the bottom of the current stack back to <loc>
353 * if <loc> is not in this stack, then the stack is reset to the beginning
354 * otherwise, the top of the stack is set to stakbot+<offset>
357 char *stakset __PARAM__((register char* loc, unsigned offset), (loc, offset)) __OTORP__(register char* loc; unsigned offset;)
360 register struct stak *sp=stakcur;
362 register struct frame *fp;
363 register int frames = 0;
369 /* see whether <loc> is in current stack frame */
370 if(loc>=(cp=sp->stakbase) && loc<=sp->stakend)
372 cp += sizeof(struct frame);
374 sfsetbuf(staksp,cp,sp->stakend-cp);
375 staksp->data = (unsigned char*)(cp + roundof(loc-cp,sizeof(char*)));
376 staksp->next = (unsigned char*)loc+offset;
379 fp = (struct frame*)cp;
382 sp->stakbase = fp->prev;
383 sp->stakend = ((struct frame*)(fp->prev))->end;
390 /* set stack back to the beginning */
393 sfsetbuf(staksp,cp,sp->stakend-cp);
395 staksp->data = staksp->next = (unsigned char*)cp;
397 return((char*)staksp->data);
401 * allocate <n> bytes on the current stack
403 char *stakalloc __PARAM__((register unsigned int n), (n)) __OTORP__(register unsigned int n;)
406 register unsigned char *old;
410 n = roundof(n,sizeof(char*));
411 if(stakleft() <= (int)n)
414 staksp->data = staksp->next = old+n;
419 * begin a new stack word of at least <n> bytes
421 char *_stakseek __PARAM__((register unsigned n), (n)) __OTORP__(register unsigned n;)
427 if(stakleft() <= (int)n)
429 staksp->next = staksp->data+n;
430 return((char*)staksp->data);
434 * advance the stack to the current top
435 * if extra is non-zero, first add a extra bytes and zero the first
437 char *stakfreeze __PARAM__((register unsigned extra), (extra)) __OTORP__(register unsigned extra;)
440 register unsigned char *old, *top;
447 if(extra > (staksp->endb-staksp->next))
449 top = (unsigned char*)stakgrow(extra);
455 staksp->next = staksp->data += roundof(top-old,sizeof(char*));
460 * copy string <str> onto the stack as a new stack word
462 char *stakcopy __PARAM__((const char* str), (str)) __OTORP__(const char* str;)
465 register unsigned char *cp = (unsigned char*)str;
468 n = roundof(cp-(unsigned char*)str,sizeof(char*));
474 strcpy((char*)(cp=staksp->data),str);
475 staksp->data = staksp->next = cp+n;
480 * add a new stack frame of size >= <n> to the current stack.
481 * if <n> > 0, copy the bytes from stakbot to staktop to the new stack
482 * if <n> is zero, then copy the remainder of the stack frame from stakbot
483 * to the end is copied into the new stack frame
486 static char *stakgrow __PARAM__((unsigned size), (size)) __OTORP__(unsigned size;)
489 register int n = size;
490 register struct stak *sp = stakcur;
491 register struct frame *fp;
493 register unsigned m = staktell();
494 register int reused = 0;
495 n += (m + sizeof(struct frame)+1);
496 if(sp->stakflags&STAK_SMALL)
498 n = roundof(n,STAK_FSIZE/16);
500 #endif /* !USE_REALLOC */
501 n = roundof(n,STAK_FSIZE);
502 /* see whether current frame can be extended */
503 if((char*)(staksp->data) == sp->stakbase+sizeof(struct frame))
505 cp = newof(sp->stakbase,char,n,0);
509 cp = newof((char*)0, char, n, 0);
510 if(!cp) cp = (*sp->stakoverflow)(n);
513 fp = (struct frame*)cp;
516 fp->prev = sp->stakbase;
519 sp->stakend = fp->end = cp+n;
522 memcpy(cp,(char*)staksp->data,m);
524 sfsetbuf(staksp,cp,sp->stakend-cp);
525 return((char*)(staksp->next = staksp->data+m));