diff options
Diffstat (limited to 'src/interfaces/ecpg/preproc/util.c')
-rw-r--r-- | src/interfaces/ecpg/preproc/util.c | 119 |
1 files changed, 97 insertions, 22 deletions
diff --git a/src/interfaces/ecpg/preproc/util.c b/src/interfaces/ecpg/preproc/util.c index cb1eca7f3cb..f177df32488 100644 --- a/src/interfaces/ecpg/preproc/util.c +++ b/src/interfaces/ecpg/preproc/util.c @@ -104,33 +104,117 @@ mm_strdup(const char *string) return new; } + /* - * String concatenation + * "Local" memory management support + * + * These functions manage memory that is only needed for a short time + * (processing of one input statement) within the ecpg grammar. + * Data allocated with these is not meant to be freed separately; + * rather it's freed by calling reclaim_local_storage() at the end + * of each statement cycle. */ +typedef struct loc_chunk +{ + struct loc_chunk *next; /* list link */ + unsigned int chunk_used; /* index of first unused byte in data[] */ + unsigned int chunk_avail; /* # bytes still available in data[] */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* actual storage */ +} loc_chunk; + +#define LOC_CHUNK_OVERHEAD MAXALIGN(offsetof(loc_chunk, data)) +#define LOC_CHUNK_MIN_SIZE 8192 + +/* Head of list of loc_chunks */ +static loc_chunk *loc_chunks = NULL; + /* - * Concatenate 2 strings, inserting a space between them unless either is empty + * Allocate local space of the requested size. * - * The input strings are freed. + * Exits on OOM. + */ +void * +loc_alloc(size_t size) +{ + void *result; + loc_chunk *cur_chunk = loc_chunks; + + /* Ensure all allocations are adequately aligned */ + size = MAXALIGN(size); + + /* Need a new chunk? */ + if (cur_chunk == NULL || size > cur_chunk->chunk_avail) + { + size_t chunk_size = Max(size, LOC_CHUNK_MIN_SIZE); + + cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD); + /* Depending on alignment rules, we could waste a bit here */ + cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data); + cur_chunk->chunk_avail = chunk_size; + /* New chunk becomes the head of the list */ + cur_chunk->next = loc_chunks; + loc_chunks = cur_chunk; + } + + result = cur_chunk->data + cur_chunk->chunk_used; + cur_chunk->chunk_used += size; + cur_chunk->chunk_avail -= size; + return result; +} + +/* + * Copy given string into local storage + */ +char * +loc_strdup(const char *string) +{ + char *result = loc_alloc(strlen(string) + 1); + + strcpy(result, string); + return result; +} + +/* + * Reclaim local storage when appropriate + */ +void +reclaim_local_storage(void) +{ + loc_chunk *cur_chunk, + *next_chunk; + + for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk) + { + next_chunk = cur_chunk->next; + free(cur_chunk); + } + loc_chunks = NULL; +} + + +/* + * String concatenation support routines. These return "local" (transient) + * storage. + */ + +/* + * Concatenate 2 strings, inserting a space between them unless either is empty */ char * -cat2_str(char *str1, char *str2) +cat2_str(const char *str1, const char *str2) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + 2); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2); strcpy(res_str, str1); if (strlen(str1) != 0 && strlen(str2) != 0) strcat(res_str, " "); strcat(res_str, str2); - free(str1); - free(str2); return res_str; } /* * Concatenate N strings, inserting spaces between them unless they are empty - * - * The input strings are freed. */ char * cat_str(int count,...) @@ -154,36 +238,27 @@ cat_str(int count,...) /* * Concatenate 2 strings, with no space between - * - * The input strings are freed. */ char * -make2_str(char *str1, char *str2) +make2_str(const char *str1, const char *str2) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + 1); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1); strcpy(res_str, str1); strcat(res_str, str2); - free(str1); - free(str2); return res_str; } /* * Concatenate 3 strings, with no space between - * - * The input strings are freed. */ char * -make3_str(char *str1, char *str2, char *str3) +make3_str(const char *str1, const char *str2, const char *str3) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1); strcpy(res_str, str1); strcat(res_str, str2); strcat(res_str, str3); - free(str1); - free(str2); - free(str3); return res_str; } |