PostgreSQL Source Code git master
util.c
Go to the documentation of this file.
1/* src/interfaces/ecpg/preproc/util.c */
2
3#include "postgres_fe.h"
4
5#include <unistd.h>
6
7#include "preproc_extern.h"
8
9static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0);
10
11
12/*
13 * Handle preprocessor errors and warnings
14 */
15static void
16vmmerror(int error_code, enum errortype type, const char *error, va_list ap)
17{
18 /* localize the error message string */
19 error = _(error);
20
21 fprintf(stderr, "%s:%d: ", input_filename, base_yylineno);
22
23 switch (type)
24 {
25 case ET_WARNING:
26 fprintf(stderr, _("WARNING: "));
27 break;
28 case ET_ERROR:
29 fprintf(stderr, _("ERROR: "));
30 break;
31 }
32
33 vfprintf(stderr, error, ap);
34
35 fprintf(stderr, "\n");
36
37 /* If appropriate, set error code to be inspected by ecpg.c */
38 switch (type)
39 {
40 case ET_WARNING:
41 break;
42 case ET_ERROR:
43 ret_value = error_code;
44 break;
45 }
46}
47
48/* Report an error or warning */
49void
50mmerror(int error_code, enum errortype type, const char *error,...)
51{
52 va_list ap;
53
54 va_start(ap, error);
55 vmmerror(error_code, type, error, ap);
56 va_end(ap);
57}
58
59/* Report an error and abandon execution */
60void
61mmfatal(int error_code, const char *error,...)
62{
63 va_list ap;
64
65 va_start(ap, error);
66 vmmerror(error_code, ET_ERROR, error, ap);
67 va_end(ap);
68
69 if (base_yyin)
70 fclose(base_yyin);
71 if (base_yyout)
72 fclose(base_yyout);
73
74 if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
75 fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
76 exit(error_code);
77}
78
79/*
80 * Basic memory management support
81 */
82
83/* malloc + error check */
84void *
85mm_alloc(size_t size)
86{
87 void *ptr = malloc(size);
88
89 if (ptr == NULL)
90 mmfatal(OUT_OF_MEMORY, "out of memory");
91
92 return ptr;
93}
94
95/* strdup + error check */
96char *
97mm_strdup(const char *string)
98{
99 char *new = strdup(string);
100
101 if (new == NULL)
102 mmfatal(OUT_OF_MEMORY, "out of memory");
103
104 return new;
105}
106
107
108/*
109 * "Local" memory management support
110 *
111 * These functions manage memory that is only needed for a short time
112 * (processing of one input statement) within the ecpg grammar.
113 * Data allocated with these is not meant to be freed separately;
114 * rather it's freed by calling reclaim_local_storage() at the end
115 * of each statement cycle.
116 */
117
118typedef struct loc_chunk
119{
120 struct loc_chunk *next; /* list link */
121 unsigned int chunk_used; /* index of first unused byte in data[] */
122 unsigned int chunk_avail; /* # bytes still available in data[] */
123 char data[FLEXIBLE_ARRAY_MEMBER]; /* actual storage */
125
126#define LOC_CHUNK_OVERHEAD MAXALIGN(offsetof(loc_chunk, data))
127#define LOC_CHUNK_MIN_SIZE 8192
128
129/* Head of list of loc_chunks */
130static loc_chunk *loc_chunks = NULL;
131
132/*
133 * Allocate local space of the requested size.
134 *
135 * Exits on OOM.
136 */
137void *
138loc_alloc(size_t size)
139{
140 void *result;
141 loc_chunk *cur_chunk = loc_chunks;
142
143 /* Ensure all allocations are adequately aligned */
144 size = MAXALIGN(size);
145
146 /* Need a new chunk? */
147 if (cur_chunk == NULL || size > cur_chunk->chunk_avail)
148 {
149 size_t chunk_size = Max(size, LOC_CHUNK_MIN_SIZE);
150
151 cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD);
152 /* Depending on alignment rules, we could waste a bit here */
153 cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data);
154 cur_chunk->chunk_avail = chunk_size;
155 /* New chunk becomes the head of the list */
156 cur_chunk->next = loc_chunks;
157 loc_chunks = cur_chunk;
158 }
159
160 result = cur_chunk->data + cur_chunk->chunk_used;
161 cur_chunk->chunk_used += size;
162 cur_chunk->chunk_avail -= size;
163 return result;
164}
165
166/*
167 * Copy given string into local storage
168 */
169char *
170loc_strdup(const char *string)
171{
172 char *result = loc_alloc(strlen(string) + 1);
173
174 strcpy(result, string);
175 return result;
176}
177
178/*
179 * Reclaim local storage when appropriate
180 */
181void
183{
184 loc_chunk *cur_chunk,
185 *next_chunk;
186
187 for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk)
188 {
189 next_chunk = cur_chunk->next;
190 free(cur_chunk);
191 }
192 loc_chunks = NULL;
193}
194
195
196/*
197 * String concatenation support routines. These return "local" (transient)
198 * storage.
199 */
200
201/*
202 * Concatenate 2 strings, inserting a space between them unless either is empty
203 */
204char *
205cat2_str(const char *str1, const char *str2)
206{
207 char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2);
208
209 strcpy(res_str, str1);
210 if (strlen(str1) != 0 && strlen(str2) != 0)
211 strcat(res_str, " ");
212 strcat(res_str, str2);
213 return res_str;
214}
215
216/*
217 * Concatenate N strings, inserting spaces between them unless they are empty
218 */
219char *
220cat_str(int count,...)
221{
222 va_list args;
223 int i;
224 char *res_str;
225
226 va_start(args, count);
227
228 res_str = va_arg(args, char *);
229
230 /* now add all other strings */
231 for (i = 1; i < count; i++)
232 res_str = cat2_str(res_str, va_arg(args, char *));
233
234 va_end(args);
235
236 return res_str;
237}
238
239/*
240 * Concatenate 2 strings, with no space between
241 */
242char *
243make2_str(const char *str1, const char *str2)
244{
245 char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1);
246
247 strcpy(res_str, str1);
248 strcat(res_str, str2);
249 return res_str;
250}
251
252/*
253 * Concatenate 3 strings, with no space between
254 */
255char *
256make3_str(const char *str1, const char *str2, const char *str3)
257{
258 char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
259
260 strcpy(res_str, str1);
261 strcat(res_str, str2);
262 strcat(res_str, str3);
263 return res_str;
264}
#define MAXALIGN(LEN)
Definition: c.h:782
#define Max(x, y)
Definition: c.h:969
#define pg_attribute_printf(f, a)
Definition: c.h:233
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:434
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
char * output_filename
Definition: ecpg.c:24
int ret_value
Definition: ecpg.c:14
#define _(x)
Definition: elog.c:90
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
void mmfatal(int error_code, const char *error,...)
Definition: util.c:61
void * loc_alloc(size_t size)
Definition: util.c:138
#define LOC_CHUNK_OVERHEAD
Definition: util.c:126
static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3
Definition: util.c:16
char * mm_strdup(const char *string)
Definition: util.c:97
struct loc_chunk loc_chunk
char * cat_str(int count,...)
Definition: util.c:220
static loc_chunk * loc_chunks
Definition: util.c:130
char * cat2_str(const char *str1, const char *str2)
Definition: util.c:205
void * mm_alloc(size_t size)
Definition: util.c:85
char * make3_str(const char *str1, const char *str2, const char *str3)
Definition: util.c:256
void reclaim_local_storage(void)
Definition: util.c:182
void mmerror(int error_code, enum errortype type, const char *error,...)
Definition: util.c:50
char * loc_strdup(const char *string)
Definition: util.c:170
#define LOC_CHUNK_MIN_SIZE
Definition: util.c:127
char * make2_str(const char *str1, const char *str2)
Definition: util.c:243
int i
Definition: isn.c:74
const void * data
#define vfprintf
Definition: port.h:242
#define OUT_OF_MEMORY
int base_yylineno
char * input_filename
FILE * base_yyin
FILE * base_yyout
static void error(void)
Definition: sql-dyntest.c:147
struct loc_chunk * next
Definition: util.c:120
char data[FLEXIBLE_ARRAY_MEMBER]
Definition: util.c:123
unsigned int chunk_used
Definition: util.c:121
unsigned int chunk_avail
Definition: util.c:122
errortype
Definition: type.h:219
@ ET_WARNING
Definition: type.h:220
@ ET_ERROR
Definition: type.h:220
const char * type