1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29/*	  All Rights Reserved  	*/
30
31
32/*
33 * University Copyright- Copyright (c) 1982, 1986, 1988
34 * The Regents of the University of California
35 * All Rights Reserved
36 *
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
39 * contributors.
40 */
41
42#pragma ident	"%Z%%M%	%I%	%E% SMI"
43
44/*
45 * mailx -- a modified version of a University of California at Berkeley
46 *	mail program
47 *
48 * Memory allocation routines.
49 * Memory handed out here are reclaimed at the top of the command
50 * loop each time, so they need not be freed.
51 */
52
53#include "rcv.h"
54#include <locale.h>
55
56static void		*lastptr;	/* addr of last buffer allocated */
57static struct strings	*lastsp;	/* last string space allocated from */
58
59/*
60 * Allocate size more bytes of space and return the address of the
61 * first byte to the caller.  An even number of bytes are always
62 * allocated so that the space will always be on a word boundary.
63 * The string spaces are of exponentially increasing size, to satisfy
64 * the occasional user with enormous string size requests.
65 */
66
67void *
68salloc(unsigned size)
69{
70	register char *t;
71	register unsigned s;
72	register struct strings *sp;
73	int index;
74
75	s = size;
76#if defined(u3b) || defined(sparc)
77	s += 3;		/* needs alignment on quad boundary */
78	s &= ~03;
79#elif defined(i386)
80	s++;
81	s &= ~01;
82#else
83#error Unknown architecture!
84#endif
85	index = 0;
86	for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) {
87		if (sp->s_topFree == NOSTR && (STRINGSIZE << index) >= s)
88			break;
89		if (sp->s_nleft >= s)
90			break;
91		index++;
92	}
93	if (sp >= &stringdope[NSPACE])
94		panic("String too large");
95	if (sp->s_topFree == NOSTR) {
96		index = sp - &stringdope[0];
97		sp->s_topFree = (char *) calloc(STRINGSIZE << index,
98		    (unsigned) 1);
99		if (sp->s_topFree == NOSTR) {
100			fprintf(stderr, gettext("No room for space %d\n"),
101			    index);
102			panic("Internal error");
103		}
104		sp->s_nextFree = sp->s_topFree;
105		sp->s_nleft = STRINGSIZE << index;
106	}
107	sp->s_nleft -= s;
108	t = sp->s_nextFree;
109	sp->s_nextFree += s;
110	lastptr = t;
111	lastsp = sp;
112	return(t);
113}
114
115/*
116 * Reallocate size bytes of space and return the address of the
117 * first byte to the caller.  The old data is copied into the new area.
118 */
119
120void *
121srealloc(void *optr, unsigned size)
122{
123	void *nptr;
124
125	/* if we just want to expand the last allocation, that's easy */
126	if (optr == lastptr) {
127		register unsigned s, delta;
128		register struct strings *sp = lastsp;
129
130		s = size;
131#if defined(u3b) || defined(sparc)
132		s += 3;		/* needs alignment on quad boundary */
133		s &= ~03;
134#elif defined(i386)
135		s++;
136		s &= ~01;
137#else
138#error Unknown architecture!
139#endif /* defined(u3b) || defined(sparc) */
140		delta = s - (sp->s_nextFree - (char *)optr);
141		if (delta <= sp->s_nleft) {
142			sp->s_nextFree += delta;
143			sp->s_nleft -= delta;
144			return (optr);
145		}
146	}
147	nptr = salloc(size);
148	if (nptr)
149		memcpy(nptr, optr, size);	/* XXX - copying too much */
150	return nptr;
151}
152
153/*
154 * Reset the string area to be empty.
155 * Called to free all strings allocated
156 * since last reset.
157 */
158void
159sreset(void)
160{
161	register struct strings *sp;
162	register int index;
163
164	if (noreset)
165		return;
166	minit();
167	index = 0;
168	for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) {
169		if (sp->s_topFree == NOSTR)
170			continue;
171		sp->s_nextFree = sp->s_topFree;
172		sp->s_nleft = STRINGSIZE << index;
173		index++;
174	}
175	lastptr = NULL;
176	lastsp = NULL;
177}
178