xref: /illumos-gate/usr/src/cmd/mailx/stralloc.c (revision 8cd45542f2a452ca0dab13d8b2d5cfa876ccbebc)
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 
56 static void		*lastptr;	/* addr of last buffer allocated */
57 static 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 
67 void *
68 salloc(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 
120 void *
121 srealloc(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  */
158 void
159 sreset(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