VirtualBox

source: kBuild/trunk/src/kash/memalloc.c@ 3505

Last change on this file since 3505 was 3480, checked in by bird, 4 years ago

kash: build fixes (darwin).

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 19.0 KB
Line 
1/* $NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if 0
36#ifndef lint
37static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
38#else
39__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
40#endif /* not lint */
41#endif
42
43#include <stdlib.h>
44#include <stddef.h>
45
46#include "shell.h"
47#include "output.h"
48#include "memalloc.h"
49#include "error.h"
50#include "machdep.h"
51#include "mystring.h"
52#include "shinstance.h"
53#include "nodes.h"
54
55/*
56 * Like malloc, but returns an error when out of space.
57 */
58
59pointer
60ckmalloc(shinstance *psh, size_t nbytes)
61{
62 pointer p;
63
64 p = sh_malloc(psh, nbytes);
65 if (p == NULL)
66 error(psh, "Out of space");
67 return p;
68}
69
70
71/*
72 * Same for realloc.
73 */
74
75pointer
76ckrealloc(struct shinstance *psh, pointer p, size_t nbytes)
77{
78 p = sh_realloc(psh, p, nbytes);
79 if (p == NULL)
80 error(psh, "Out of space");
81 return p;
82}
83
84
85/*
86 * Make a copy of a string in safe storage.
87 */
88
89char *
90savestr(struct shinstance *psh, const char *s)
91{
92 char *p;
93 size_t len = strlen(s);
94
95 p = ckmalloc(psh, len + 1);
96 memcpy(p, s, len + 1);
97 return p;
98}
99
100
101/*
102 * Parse trees for commands are allocated in lifo order, so we use a stack
103 * to make this more efficient, and also to avoid all sorts of exception
104 * handling code to handle interrupts in the middle of a parse.
105 *
106 * The size 504 was chosen because the Ultrix malloc handles that size
107 * well.
108 */
109
110//#define MINSIZE 504 /* minimum size of a block */
111
112//struct stack_block {
113// struct stack_block *prev;
114// char space[MINSIZE];
115//};
116
117//struct stack_block stackbase;
118//struct stack_block *stackp = &stackbase;
119//struct stackmark *markp;
120//char *stacknxt = stackbase.space;
121//int stacknleft = MINSIZE;
122//int sstrnleft;
123//int herefd = -1;
124
125pointer
126stalloc(shinstance *psh, size_t nbytes)
127{
128 char *p;
129
130 nbytes = SHELL_ALIGN(nbytes);
131 if (nbytes > (size_t)psh->stacknleft || psh->stacknleft < 0) {
132 size_t blocksize;
133 struct stack_block *sp;
134
135 blocksize = nbytes;
136 if (blocksize < MINSIZE)
137 blocksize = MINSIZE;
138 INTOFF;
139 sp = ckmalloc(psh, sizeof(struct stack_block) - MINSIZE + blocksize);
140 sp->prev = psh->stackp;
141 psh->stacknxt = sp->space;
142 psh->stacknleft = (int)blocksize;
143 psh->stackp = sp;
144 INTON;
145 }
146 p = psh->stacknxt;
147 psh->stacknxt += nbytes;
148 psh->stacknleft -= (int)nbytes;
149 return p;
150}
151
152
153char *
154stsavestr(struct shinstance *psh, const char *src)
155{
156 if (src) {
157 size_t size = strlen(src) + 1;
158 char *dst = (char *)stalloc(psh, size);
159 return (char *)memcpy(dst, src, size);
160 }
161 return NULL;
162}
163
164
165void
166stunalloc(shinstance *psh, pointer p)
167{
168 if (p == NULL) { /*DEBUG */
169 shfile_write(&psh->fdtab, 2, "stunalloc\n", 10);
170 sh_abort(psh);
171 }
172 psh->stacknleft += (int)(psh->stacknxt - (char *)p);
173 psh->stacknxt = p;
174}
175
176
177
178void
179setstackmark(shinstance *psh, struct stackmark *mark)
180{
181 mark->stackp = psh->stackp;
182 mark->stacknxt = psh->stacknxt;
183 mark->stacknleft = psh->stacknleft;
184 mark->marknext = psh->markp;
185#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
186 mark->pstacksize = psh->pstacksize;
187#endif
188 psh->markp = mark;
189}
190
191
192void
193popstackmark(shinstance *psh, struct stackmark *mark)
194{
195 struct stack_block *sp;
196
197 INTOFF;
198 psh->markp = mark->marknext;
199 while (psh->stackp != mark->stackp) {
200 sp = psh->stackp;
201 psh->stackp = sp->prev;
202 ckfree(psh, sp);
203 }
204 psh->stacknxt = mark->stacknxt;
205 psh->stacknleft = mark->stacknleft;
206
207#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
208 pstackpop(psh, mark->pstacksize);
209#endif
210 INTON;
211}
212
213
214/*
215 * When the parser reads in a string, it wants to stick the string on the
216 * stack and only adjust the stack pointer when it knows how big the
217 * string is. Stackblock (defined in stack.h) returns a pointer to a block
218 * of space on top of the stack and stackblocklen returns the length of
219 * this block. Growstackblock will grow this space by at least one byte,
220 * possibly moving it (like realloc). Grabstackblock actually allocates the
221 * part of the block that has been used.
222 */
223
224void
225growstackblock(shinstance *psh)
226{
227 int newlen = SHELL_ALIGN(psh->stacknleft * 2 + 100);
228
229 if (psh->stacknxt == psh->stackp->space && psh->stackp != &psh->stackbase) {
230 struct stack_block *oldstackp;
231 struct stackmark *xmark;
232 struct stack_block *sp;
233
234 INTOFF;
235 oldstackp = psh->stackp;
236 sp = psh->stackp;
237 psh->stackp = sp->prev;
238 sp = ckrealloc(psh, (pointer)sp,
239 sizeof(struct stack_block) - MINSIZE + newlen);
240 sp->prev = psh->stackp;
241 psh->stackp = sp;
242 psh->stacknxt = sp->space;
243 psh->stacknleft = newlen;
244
245 /*
246 * Stack marks pointing to the start of the old block
247 * must be relocated to point to the new block
248 */
249 xmark = psh->markp;
250 while (xmark != NULL && xmark->stackp == oldstackp) {
251 xmark->stackp = psh->stackp;
252 xmark->stacknxt = psh->stacknxt;
253 xmark->stacknleft = psh->stacknleft;
254 xmark = xmark->marknext;
255 }
256 INTON;
257 } else {
258 char *oldspace = psh->stacknxt;
259 int oldlen = psh->stacknleft;
260 char *p = stalloc(psh, newlen);
261
262 (void)memcpy(p, oldspace, oldlen);
263 psh->stacknxt = p; /* free the space */
264 psh->stacknleft += newlen; /* we just allocated */
265 }
266}
267
268void
269grabstackblock(shinstance *psh, int len)
270{
271 len = SHELL_ALIGN(len);
272 psh->stacknxt += len;
273 psh->stacknleft -= len;
274}
275
276/*
277 * The following routines are somewhat easier to use than the above.
278 * The user declares a variable of type STACKSTR, which may be declared
279 * to be a register. The macro STARTSTACKSTR initializes things. Then
280 * the user uses the macro STPUTC to add characters to the string. In
281 * effect, STPUTC(psh, c, p) is the same as *p++ = c except that the stack is
282 * grown as necessary. When the user is done, she can just leave the
283 * string there and refer to it using stackblock(psh). Or she can allocate
284 * the space for it using grabstackstr(). If it is necessary to allow
285 * someone else to use the stack temporarily and then continue to grow
286 * the string, the user should use grabstack to allocate the space, and
287 * then call ungrabstr(p) to return to the previous mode of operation.
288 *
289 * USTPUTC is like STPUTC except that it doesn't check for overflow.
290 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
291 * is space for at least one character.
292 */
293
294char *
295growstackstr(shinstance *psh)
296{
297 int len = stackblocksize(psh);
298 if (psh->herefd >= 0 && len >= 1024) {
299 xwrite(psh, psh->herefd, stackblock(psh), len);
300 psh->sstrnleft = len - 1;
301 return stackblock(psh);
302 }
303 growstackblock(psh);
304 psh->sstrnleft = stackblocksize(psh) - len - 1;
305 return stackblock(psh) + len;
306}
307
308/*
309 * Called from CHECKSTRSPACE.
310 */
311
312char *
313makestrspace(shinstance *psh)
314{
315 int len = stackblocksize(psh) - psh->sstrnleft;
316 growstackblock(psh);
317 psh->sstrnleft = stackblocksize(psh) - len;
318 return stackblock(psh) + len;
319}
320
321
322/*
323 * Got better control having a dedicated function for this.
324 *
325 * Was: #define grabstackstr(psh, p) stalloc((psh), stackblocksize(psh) - (psh)->sstrnleft)
326 */
327char *
328grabstackstr(shinstance *psh, char *end)
329{
330 char * const pstart = stackblock(psh);
331 size_t nbytes = (size_t)(end - pstart);
332
333 kHlpAssert((uintptr_t)end >= (uintptr_t)pstart);
334 /*kHlpAssert(end[-1] == '\0'); - not if it's followed by ungrabstrackstr(), sigh. */
335 kHlpAssert(SHELL_ALIGN((uintptr_t)pstart) == (uintptr_t)pstart);
336 kHlpAssert(stackblocksize(psh) - psh->sstrnleft >= (ssize_t)nbytes);
337
338 nbytes = SHELL_ALIGN(nbytes);
339 psh->stacknxt += nbytes;
340 psh->stacknleft -= (int)nbytes;
341 kHlpAssert(psh->stacknleft >= 0);
342
343 return pstart;
344}
345
346void
347ungrabstackstr(shinstance *psh, char *s, char *p)
348{
349 kHlpAssert((size_t)(psh->stacknxt - p) <= SHELL_SIZE);
350 kHlpAssert((uintptr_t)s >= (uintptr_t)&psh->stackp->space[0]);
351 kHlpAssert((uintptr_t)p >= (uintptr_t)s);
352
353 psh->stacknleft += (int)(psh->stacknxt - s);
354 psh->stacknxt = s;
355 psh->sstrnleft = (int)(psh->stacknleft - (p - s));
356
357}
358
359
360/*
361 * Parser stack allocator.
362 */
363#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
364
365unsigned pstackrelease(shinstance *psh, pstack_block *pst, const char *caller)
366{
367 unsigned refs;
368 if (pst) {
369 refs = sh_atomic_dec(&pst->refs);
370 TRACE2((NULL, "pstackrelease: %p - %u refs (%s)\n", pst, refs, caller)); K_NOREF(caller);
371 if (refs == 0) {
372 struct stack_block *top;
373 while ((top = pst->top) != &pst->first) {
374 pst->top = top->prev;
375 kHlpAssert(pst->top);
376 top->prev = NULL;
377 sh_free(psh, top);
378 }
379 pst->nextbyte = NULL;
380 pst->top = NULL;
381
382 if (!psh->freepstack)
383 psh->freepstack = pst;
384 else
385 sh_free(psh, pst);
386 }
387 } else
388 refs = 0;
389 return refs;
390}
391
392void pstackpop(shinstance *psh, unsigned target)
393{
394 kHlpAssert(target <= psh->pstacksize);
395 while (target < psh->pstacksize) {
396 unsigned idx = --psh->pstacksize;
397 pstack_block *pst = psh->pstack[idx];
398 psh->pstack[idx] = NULL;
399 if (psh->curpstack == pst) {
400 pstack_block *pstnext;
401 if (idx <= 0 || (pstnext = psh->pstack[idx - 1])->done)
402 psh->curpstack = NULL;
403 else
404 psh->curpstack = pstnext;
405 }
406 pstackrelease(psh, pst, "popstackmark");
407 }
408
409# ifndef NDEBUG
410 if (psh->curpstack) {
411 unsigned i;
412 for (i = 0; i < psh->pstacksize; i++)
413 if (psh->curpstack == psh->pstack[i])
414 break;
415 kHlpAssert(i < psh->pstacksize);
416 }
417# endif
418}
419
420
421unsigned pstackretain(pstack_block *pst)
422{
423 unsigned refs = sh_atomic_inc(&pst->refs);
424 kHlpAssert(refs > 1);
425 kHlpAssert(refs < 256 /* bogus, but useful */);
426 return refs;
427}
428
429K_INLINE void pstackpush(shinstance *psh, pstack_block *pst)
430{
431 unsigned i = psh->pstacksize;
432 if (i + 1 < psh->pstackalloced) {
433 /* likely, except for the first time */
434 } else {
435 psh->pstack = (pstack_block **)ckrealloc(psh, psh->pstack, sizeof(psh->pstack[0]) * (i + 32));
436 memset(&psh->pstack[i], 0, sizeof(psh->pstack[0]) * 32);
437 }
438 psh->pstack[i] = pst;
439 psh->pstacksize = i + 1;
440}
441
442/* Does not make it current! */
443unsigned pstackretainpush(shinstance *psh, pstack_block *pst)
444{
445 unsigned refs = pstackretain(pst);
446 pstackpush(psh, pst);
447 TRACE2((psh, "pstackretainpush: %p - entry %u - %u refs\n", pst, psh->pstacksize - 1, refs));
448 return refs;
449}
450
451pstack_block *pstackallocpush(shinstance *psh)
452{
453 size_t const blocksize = offsetof(pstack_block, first.space) + MINSIZE;
454 pstack_block *pst;
455
456 INTOFF;
457
458 /*
459 * Allocate and initialize it.
460 */
461 pst = psh->freepstack;
462 if (pst)
463 psh->freepstack = NULL;
464 else
465 pst = (pstack_block *)ckmalloc(psh, blocksize);
466 pst->nextbyte = &pst->first.space[0];
467 pst->avail = blocksize - offsetof(pstack_block, first.space);
468 pst->topsize = blocksize - offsetof(pstack_block, first.space);
469 pst->strleft = 0;
470 pst->top = &pst->first;
471 pst->allocations = 0;
472 pst->bytesalloced = 0;
473 pst->nodesalloced = 0;
474 pst->entriesalloced = 0;
475 pst->strbytesalloced = 0;
476 pst->blocks = 0;
477 pst->fragmentation = 0;
478 pst->refs = 1;
479 pst->done = K_FALSE;
480 pst->first.prev = NULL;
481
482 /*
483 * Push it onto the stack and make it current.
484 */
485 pstackpush(psh, pst);
486 psh->curpstack = pst;
487
488 INTON;
489 TRACE2((psh, "pstackallocpush: %p - entry %u\n", pst, psh->pstacksize - 1));
490 return pst;
491}
492
493/**
494 * Marks the block as done, preventing it from being marked current again.
495 */
496void pstackmarkdone(pstack_block *pst)
497{
498 pst->done = K_TRUE;
499}
500
501/**
502 * Allocates and pushes a new block onto the stack, min payload size @a nbytes.
503 */
504static void pstallocnewblock(shinstance *psh, pstack_block *pst, size_t nbytes)
505{
506 /* Allocate a new stack node. */
507 struct stack_block *sp;
508 size_t const blocksize = nbytes <= MINSIZE
509 ? offsetof(struct stack_block, space) + MINSIZE
510 : K_ALIGN_Z(nbytes + offsetof(struct stack_block, space), 1024);
511
512 INTOFF;
513 sp = ckmalloc(psh, blocksize);
514 sp->prev = pst->top;
515 pst->fragmentation += pst->avail;
516 pst->topsize = blocksize - offsetof(struct stack_block, space);
517 pst->avail = blocksize - offsetof(struct stack_block, space);
518 pst->nextbyte = sp->space;
519 pst->top = sp;
520 pst->blocks += 1;
521 INTON;
522}
523
524/**
525 * Tries to grow the current stack block to hold a minimum of @a nbytes,
526 * will allocate a new block and copy over pending string bytes if that's not
527 * possible.
528 */
529static void pstgrowblock(shinstance *psh, pstack_block *pst, size_t nbytes, size_t tocopy)
530{
531 struct stack_block *top = pst->top;
532 size_t blocksize;
533
534 kHlpAssert(pst->avail < nbytes); /* only called when we need more space */
535 kHlpAssert(tocopy <= pst->avail);
536
537 /* Double the size used thus far and add some fudge and alignment. Make
538 sure to at least allocate MINSIZE. */
539 blocksize = K_MAX(K_ALIGN_Z(pst->avail * 2 + 100 + offsetof(struct stack_block, space), 64), MINSIZE);
540
541 /* If that isn't sufficient, do request size w/ some fudge and alignment. */
542 if (blocksize < nbytes + offsetof(struct stack_block, space))
543 blocksize = K_ALIGN_Z(nbytes + offsetof(struct stack_block, space) + 100, 1024);
544
545 /*
546 * Reallocate the current stack node if we can.
547 */
548 if ( pst->nextbyte == &top->space[0] /* can't have anything else in the block */
549 && top->prev != NULL /* first block is embedded in pst and cannot be reallocated */ ) {
550 top = (struct stack_block *)ckrealloc(psh, top, blocksize);
551 pst->top = top;
552 pst->topsize = blocksize - offsetof(struct stack_block, space);
553 pst->avail = blocksize - offsetof(struct stack_block, space);
554 pst->nextbyte = top->space;
555 }
556 /*
557 * Otherwise allocate a new node and copy over the avail bytes
558 * from the old one.
559 */
560 else {
561 char const * const copysrc = pst->nextbyte;
562 pstallocnewblock(psh, pst, nbytes);
563 kHlpAssert(pst->avail >= nbytes);
564 kHlpAssert(pst->avail >= tocopy);
565 memcpy(pst->nextbyte, copysrc, tocopy);
566 }
567}
568
569K_INLINE void *pstallocint(shinstance *psh, pstack_block *pst, size_t nbytes)
570{
571 void *ret;
572
573 /*
574 * Align the size and make sure we've got sufficient bytes available:
575 */
576 nbytes = SHELL_ALIGN(nbytes);
577 if (pst->avail >= nbytes && (ssize_t)pst->avail >= 0) { /* likely*/ }
578 else pstallocnewblock(psh, pst, nbytes);
579
580 /*
581 * Carve out the return block.
582 */
583 ret = pst->nextbyte;
584 pst->nextbyte += nbytes;
585 pst->avail -= nbytes;
586 pst->bytesalloced += nbytes;
587 pst->allocations += 1;
588 return ret;
589}
590
591#endif /* KASH_SEPARATE_PARSER_ALLOCATOR */
592
593
594void *pstalloc(struct shinstance *psh, size_t nbytes)
595{
596#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
597 return pstallocint(psh, psh->curpstack, nbytes);
598#else
599 return stalloc(psh, nbytes);
600#endif
601}
602
603union node *pstallocnode(struct shinstance *psh, size_t nbytes)
604{
605#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
606 pstack_block * const pst = psh->curpstack;
607 union node * const ret = (union node *)pstallocint(psh, pst, nbytes);
608 pst->nodesalloced++;
609 ret->pblock = pst;
610 return ret;
611#else
612 return (union node *)pstalloc(psh, nbytes);
613#endif
614}
615
616struct nodelist *pstalloclist(struct shinstance *psh)
617{
618#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
619 pstack_block *pst = psh->curpstack;
620 pst->entriesalloced++;
621 return (struct nodelist *)pstallocint(psh, pst, sizeof(struct nodelist));
622#endif
623 return (struct nodelist *)pstalloc(psh, sizeof(struct nodelist));
624}
625
626char *pstsavestr(struct shinstance *psh, const char *str)
627{
628 if (str) {
629 size_t const nbytes = strlen(str) + 1;
630#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
631 pstack_block *pst = psh->curpstack;
632 pst->strbytesalloced += SHELL_ALIGN(nbytes);
633 return (char *)memcpy(pstallocint(psh, pst, nbytes), str, nbytes);
634#else
635 return (char *)memcpy(pstalloc(psh, nbytes), str, nbytes);
636#endif
637 }
638 return NULL;
639}
640
641char *pstmakestrspace(struct shinstance *psh, size_t minbytes, char *end)
642{
643#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
644 pstack_block *pst = psh->curpstack;
645 size_t const len = end - pst->nextbyte;
646
647 kHlpAssert(pst->avail - pst->strleft == len);
648 TRACE2((psh, "pstmakestrspace: len=%u minbytes=%u (=> %u)\n", len, minbytes, len + minbytes));
649
650 pstgrowblock(psh, pst, minbytes + len, len);
651
652 pst->strleft = pst->avail - len;
653 return pst->nextbyte + len;
654
655#else
656 size_t const len = end - stackblock(psh);
657
658 kHlpAssert(stackblocksize(psh) - psh->sstrnleft == len);
659 TRACE2((psh, "pstmakestrspace: len=%u minbytes=%u (=> %u)\n", len, minbytes, len + minbytes));
660
661 minbytes += len;
662 while (stackblocksize(psh) < minbytes)
663 growstackblock(psh);
664
665 psh->sstrnleft = (int)(stackblocksize(psh) - len);
666 return (char *)stackblock(psh) + len;
667#endif
668}
669
670/* PSTPUTC helper */
671char *pstputcgrow(shinstance *psh, char *end, char c)
672{
673#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
674 pstack_block *pst = psh->curpstack;
675 pst->strleft++; /* PSTPUTC() already incremented it. */
676 end = pstmakestrspace(psh, 1, end);
677 kHlpAssert(pst->strleft > 0);
678 pst->strleft--;
679#else
680 psh->sstrnleft++; /* PSTPUTC() already incremented it. */
681 end = pstmakestrspace(psh, 1, end);
682 kHlpAssert(psh->sstrnleft > 0);
683 psh->sstrnleft--;
684#endif
685 *end++ = c;
686 return end;
687}
688
689
690char *pstgrabstr(struct shinstance *psh, char *end)
691{
692#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
693 pstack_block *pst = psh->curpstack;
694 char * const pstart = pst->nextbyte;
695 size_t nbytes = (size_t)(end - pstart);
696
697 kHlpAssert((uintptr_t)end > (uintptr_t)pstart);
698 kHlpAssert(end[-1] == '\0');
699 kHlpAssert(SHELL_ALIGN((uintptr_t)pstart) == (uintptr_t)pstart);
700 kHlpAssert(pst->avail - pst->strleft >= nbytes);
701
702 nbytes = SHELL_ALIGN(nbytes); /** @todo don't align strings, align the other allocations. */
703 pst->nextbyte += nbytes;
704 pst->avail -= nbytes;
705 pst->strbytesalloced += nbytes;
706
707 return pstart;
708
709#else
710 char * const pstart = stackblock(psh);
711 size_t nbytes = (size_t)(end - pstart);
712
713 kHlpAssert((uintptr_t)end > (uintptr_t)pstart);
714 kHlpAssert(end[-1] == '\0');
715 kHlpAssert(SHELL_ALIGN((uintptr_t)pstart) == (uintptr_t)pstart);
716 kHlpAssert(stackblocksize(psh) - psh->sstrnleft >= nbytes);
717
718 nbytes = SHELL_ALIGN(nbytes); /** @todo don't align strings, align the other allocations. */
719 psh->stacknxt += nbytes;
720 psh->stacknleft -= (int)nbytes;
721
722 return pstart;
723#endif
724}
725
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette