/**************************************************************************** Copyright (C) 1987-2005 by Jeffery P. Hansen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************/ /* ycmalloc.cc: Temporary Memory Pool Last edit by hansen on Tue Jun 8 11:58:39 2004 */ /* The temporary memory pool is used to store return values form yacc grammar rules. Memory is allocated using the ycmalloc call, and all allocated memory is freed by a call to ycfreeall. Generally, freeall is called after processing a siginificant parse unit such as a module. By using the memory pool we do not need to worry about freeing temporary values used by the parser. */ #include #include #include #include #include #include "config.h" #include "ycmalloc.h" struct yc_pool_elem { struct yc_pool_elem *pe_next; /* Next pool */ int pe_istop; /* Is this the top of a context */ int pe_size; /* Size of this pool */ int pe_last; /* One byte past last used byte */ char *pe_data; /* Data buffer of pool */ }; static struct yc_pool_elem *yc_pool = 0; /* Current pool */ void yc_growpool() { struct yc_pool_elem *P = (struct yc_pool_elem*) malloc(sizeof(struct yc_pool_elem)); P->pe_next = yc_pool; P->pe_size = YC_POOL_SIZE; P->pe_last = 0; P->pe_istop = 0; P->pe_data = (char*) malloc(YC_POOL_SIZE); yc_pool = P; } void yc_pushpool() { yc_growpool(); yc_pool->pe_istop = 1; } /* Put a distinctive pattern into the pool so that any objects we forgot to copy will be obvious. */ void yc_poppool() { size_t i; struct yc_pool_elem *D = 0; while (yc_pool) { D = yc_pool; yc_pool = yc_pool->pe_next; for (i = 0;i < YC_POOL_SIZE-(sizeof( size_t ) - 1) ;i += sizeof( size_t ) ) { #if TKGATE_ARCHITECTURE == 32 *((size_t*)&D->pe_data[i]) = 0xdeadf001; #elif TKGATE_ARCHITECTURE == 64 *((size_t*)&D->pe_data[i]) = 0xdeadf001deadf001; #else printf( "TKGATE_ARCHITECTURE = %d - Unsupported - Aborting\n", TKGATE_ARCHITECTURE ); abort(); #endif } free(D->pe_data); free(D); if (yc_pool && yc_pool->pe_istop) break; } } void yc_setup() { if (!yc_pool) yc_pushpool(); } void yc_freeall() { if (yc_pool) { yc_poppool(); yc_pushpool(); } } char *yc_strdup(const char *S) { long L; char *N; if (!S) return 0; L = strlen(S); N = (char*)yc_malloc(L+1,ALGN_BYTE); strcpy(N,S); return N; } void *yc_malloc(long L,int Algn) { char *P; int Remaining = yc_pool->pe_size - yc_pool->pe_last; /* Bytes remaining in pool */ assert(L < YC_POOL_SIZE); if (Algn + L > Remaining) yc_growpool(); /* Align offset to next Algn boundary */ yc_pool->pe_last = ((yc_pool->pe_last-1)|(Algn-1))+1; P = &yc_pool->pe_data[yc_pool->pe_last]; yc_pool->pe_last += L; return P; } char *yc_sprintf(char *s,...) { va_list ap; char buf[1024]; va_start(ap,s); vsprintf(buf,s,ap); va_end(ap); return yc_strdup(buf); }