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 
9 static 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  */
15 static void
16 vmmerror(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 */
49 void
50 mmerror(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 */
60 void
61 mmfatal(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 */
84 void *
85 mm_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 */
96 char *
97 mm_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 
118 typedef 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 */
130 static loc_chunk *loc_chunks = NULL;
131 
132 /*
133  * Allocate local space of the requested size.
134  *
135  * Exits on OOM.
136  */
137 void *
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  */
169 char *
170 loc_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  */
181 void
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  */
204 char *
205 cat2_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  */
219 char *
220 cat_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  */
242 char *
243 make2_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  */
255 char *
256 make3_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:802
#define Max(x, y)
Definition: c.h:989
#define pg_attribute_printf(f, a)
Definition: c.h:194
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:401
char * output_filename
Definition: ecpg.c:23
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
#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
struct loc_chunk loc_chunk
char * cat_str(int count,...)
Definition: util.c:220
char * loc_strdup(const char *string)
Definition: util.c:170
char * mm_strdup(const char *string)
Definition: util.c:97
static loc_chunk * loc_chunks
Definition: util.c:130
char * cat2_str(const char *str1, const char *str2)
Definition: util.c:205
char * make2_str(const char *str1, const char *str2)
Definition: util.c:243
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
void * loc_alloc(size_t size)
Definition: util.c:138
#define LOC_CHUNK_MIN_SIZE
Definition: util.c:127
void * mm_alloc(size_t size)
Definition: util.c:85
int i
Definition: isn.c:73
va_end(args)
vfprintf(stderr, fmt, args)
exit(1)
va_start(args, fmt)
const void * data
#define fprintf
Definition: port.h:242
#define OUT_OF_MEMORY
int base_yylineno
char * input_filename
FILE * base_yyin
FILE * base_yyout
static pg_noinline void Size size
Definition: slab.c:607
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:218
@ ET_WARNING
Definition: type.h:219
@ ET_ERROR
Definition: type.h:219
const char * type