From f18231e817599246fc99a798c9bf57ab785db91f Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 14 Oct 2024 13:47:59 -0400 Subject: [PATCH] ecpg: move some functions into a new file ecpg/preproc/util.c. mm_alloc and mm_strdup were in type.c, which seems a completely random choice. No doubt the original author thought two small functions didn't deserve their own file. But I'm about to add some more memory-management stuff beside them, so let's put them in a less surprising place. This seems like a better home for mmerror, mmfatal, and the cat_str/make_str family, too. Discussion: https://postgr.es/m/2011420.1713493114@sss.pgh.pa.us --- src/interfaces/ecpg/preproc/Makefile | 1 + src/interfaces/ecpg/preproc/ecpg.header | 129 ------------- src/interfaces/ecpg/preproc/meson.build | 1 + src/interfaces/ecpg/preproc/preproc_extern.h | 4 + src/interfaces/ecpg/preproc/type.c | 24 --- src/interfaces/ecpg/preproc/util.c | 189 +++++++++++++++++++ 6 files changed, 195 insertions(+), 153 deletions(-) create mode 100644 src/interfaces/ecpg/preproc/util.c diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index c56fb92f4a4..4f403da9355 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -36,6 +36,7 @@ OBJS = \ preproc.o \ type.o \ typename.o \ + util.o \ variable.o # where to find gen_keywordlist.pl and subsidiary files diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header index 8df6248c976..929ffa97aa0 100644 --- a/src/interfaces/ecpg/preproc/ecpg.header +++ b/src/interfaces/ecpg/preproc/ecpg.header @@ -60,137 +60,8 @@ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; static struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NULL}, 0}; -static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0); - static bool check_declared_list(const char *name); -/* - * Handle parsing errors and warnings - */ -static void -vmmerror(int error_code, enum errortype type, const char *error, va_list ap) -{ - /* localize the error message string */ - error = _(error); - - fprintf(stderr, "%s:%d: ", input_filename, base_yylineno); - - switch (type) - { - case ET_WARNING: - fprintf(stderr, _("WARNING: ")); - break; - case ET_ERROR: - fprintf(stderr, _("ERROR: ")); - break; - } - - vfprintf(stderr, error, ap); - - fprintf(stderr, "\n"); - - switch (type) - { - case ET_WARNING: - break; - case ET_ERROR: - ret_value = error_code; - break; - } -} - -void -mmerror(int error_code, enum errortype type, const char *error,...) -{ - va_list ap; - - va_start(ap, error); - vmmerror(error_code, type, error, ap); - va_end(ap); -} - -void -mmfatal(int error_code, const char *error,...) -{ - va_list ap; - - va_start(ap, error); - vmmerror(error_code, ET_ERROR, error, ap); - va_end(ap); - - if (base_yyin) - fclose(base_yyin); - if (base_yyout) - fclose(base_yyout); - - if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0) - fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename); - exit(error_code); -} - -/* - * string concatenation - */ - -static char * -cat2_str(char *str1, char *str2) -{ - char *res_str = (char *) mm_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; -} - -static char * -cat_str(int count,...) -{ - va_list args; - int i; - char *res_str; - - va_start(args, count); - - res_str = va_arg(args, char *); - - /* now add all other strings */ - for (i = 1; i < count; i++) - res_str = cat2_str(res_str, va_arg(args, char *)); - - va_end(args); - - return res_str; -} - -static char * -make2_str(char *str1, char *str2) -{ - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + 1); - - strcpy(res_str, str1); - strcat(res_str, str2); - free(str1); - free(str2); - return res_str; -} - -static char * -make3_str(char *str1, char *str2, char *str3) -{ - char *res_str = (char *) mm_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; -} /* * "Location tracking" support. We commandeer Bison's location tracking diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build index aebb88bb589..2fb1402c70c 100644 --- a/src/interfaces/ecpg/preproc/meson.build +++ b/src/interfaces/ecpg/preproc/meson.build @@ -10,6 +10,7 @@ ecpg_sources = files( 'output.c', 'parser.c', 'type.c', + 'util.c', 'variable.c', ) diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h index da939674620..29329ccd891 100644 --- a/src/interfaces/ecpg/preproc/preproc_extern.h +++ b/src/interfaces/ecpg/preproc/preproc_extern.h @@ -82,6 +82,10 @@ extern int base_yylex(void); extern void base_yyerror(const char *error); extern void *mm_alloc(size_t size); extern char *mm_strdup(const char *string); +extern char *cat2_str(char *str1, char *str2); +extern char *cat_str(int count,...); +extern char *make2_str(char *str1, char *str2); +extern char *make3_str(char *str1, char *str2, char *str3); extern void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3, 4); extern void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2, 3) pg_attribute_noreturn(); extern void output_get_descr_header(char *desc_name); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index a842bb6a1fe..5610a8dc76b 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -8,30 +8,6 @@ static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL}; -/* malloc + error check */ -void * -mm_alloc(size_t size) -{ - void *ptr = malloc(size); - - if (ptr == NULL) - mmfatal(OUT_OF_MEMORY, "out of memory"); - - return ptr; -} - -/* strdup + error check */ -char * -mm_strdup(const char *string) -{ - char *new = strdup(string); - - if (new == NULL) - mmfatal(OUT_OF_MEMORY, "out of memory"); - - return new; -} - /* duplicate memberlist */ struct ECPGstruct_member * ECPGstruct_member_dup(struct ECPGstruct_member *rm) diff --git a/src/interfaces/ecpg/preproc/util.c b/src/interfaces/ecpg/preproc/util.c new file mode 100644 index 00000000000..cb1eca7f3cb --- /dev/null +++ b/src/interfaces/ecpg/preproc/util.c @@ -0,0 +1,189 @@ +/* src/interfaces/ecpg/preproc/util.c */ + +#include "postgres_fe.h" + +#include + +#include "preproc_extern.h" + +static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0); + + +/* + * Handle preprocessor errors and warnings + */ +static void +vmmerror(int error_code, enum errortype type, const char *error, va_list ap) +{ + /* localize the error message string */ + error = _(error); + + fprintf(stderr, "%s:%d: ", input_filename, base_yylineno); + + switch (type) + { + case ET_WARNING: + fprintf(stderr, _("WARNING: ")); + break; + case ET_ERROR: + fprintf(stderr, _("ERROR: ")); + break; + } + + vfprintf(stderr, error, ap); + + fprintf(stderr, "\n"); + + /* If appropriate, set error code to be inspected by ecpg.c */ + switch (type) + { + case ET_WARNING: + break; + case ET_ERROR: + ret_value = error_code; + break; + } +} + +/* Report an error or warning */ +void +mmerror(int error_code, enum errortype type, const char *error,...) +{ + va_list ap; + + va_start(ap, error); + vmmerror(error_code, type, error, ap); + va_end(ap); +} + +/* Report an error and abandon execution */ +void +mmfatal(int error_code, const char *error,...) +{ + va_list ap; + + va_start(ap, error); + vmmerror(error_code, ET_ERROR, error, ap); + va_end(ap); + + if (base_yyin) + fclose(base_yyin); + if (base_yyout) + fclose(base_yyout); + + if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0) + fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename); + exit(error_code); +} + +/* + * Basic memory management support + */ + +/* malloc + error check */ +void * +mm_alloc(size_t size) +{ + void *ptr = malloc(size); + + if (ptr == NULL) + mmfatal(OUT_OF_MEMORY, "out of memory"); + + return ptr; +} + +/* strdup + error check */ +char * +mm_strdup(const char *string) +{ + char *new = strdup(string); + + if (new == NULL) + mmfatal(OUT_OF_MEMORY, "out of memory"); + + return new; +} + +/* + * String concatenation + */ + +/* + * Concatenate 2 strings, inserting a space between them unless either is empty + * + * The input strings are freed. + */ +char * +cat2_str(char *str1, char *str2) +{ + char *res_str = (char *) mm_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,...) +{ + va_list args; + int i; + char *res_str; + + va_start(args, count); + + res_str = va_arg(args, char *); + + /* now add all other strings */ + for (i = 1; i < count; i++) + res_str = cat2_str(res_str, va_arg(args, char *)); + + va_end(args); + + return res_str; +} + +/* + * Concatenate 2 strings, with no space between + * + * The input strings are freed. + */ +char * +make2_str(char *str1, char *str2) +{ + char *res_str = (char *) mm_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) +{ + char *res_str = (char *) mm_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; +}