From aeea50127725058daeef294bf5b10f304e1d14bb Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 12 Mar 2018 13:44:15 -0400 Subject: [PATCH v2 3/3] Move strtoint() to common Several places uses similar code to convert a string to an int, so take the function that we already had and make it globally available. --- src/backend/nodes/read.c | 11 +++++------ src/backend/parser/scan.l | 9 ++++----- src/backend/utils/adt/datetime.c | 18 +----------------- src/common/string.c | 15 +++++++++++++++ src/include/common/string.h | 1 + src/interfaces/ecpg/pgtypeslib/Makefile | 6 +++++- src/interfaces/ecpg/pgtypeslib/interval.c | 16 ++-------------- src/interfaces/ecpg/preproc/pgc.l | 10 +++++----- 8 files changed, 38 insertions(+), 48 deletions(-) diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index 6e9fa45e37..5437fa3d0a 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -21,6 +21,7 @@ #include +#include "common/string.h" #include "nodes/pg_list.h" #include "nodes/readfuncs.h" #include "nodes/value.h" @@ -216,17 +217,15 @@ nodeTokenType(char *token, int length) /* * Yes. Figure out whether it is integral or float; this requires * both a syntax check and a range check. strtol() can do both for us. - * We know the token will end at a character that strtol will stop at, + * We know the token will end at a character that strtoint will stop at, * so we do not need to modify the string. */ - long val; + int val; char *endptr; errno = 0; - val = strtol(token, &endptr, 10); - if (endptr != token + length || errno == ERANGE || - /* check for overflow of int */ - val != (int) val) + val = strtoint(token, &endptr, 10); + if (endptr != token + length || errno == ERANGE) return T_Float; return T_Integer; } diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 97d4dee628..0cd782827a 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -34,6 +34,7 @@ #include #include +#include "common/string.h" #include "parser/gramparse.h" #include "parser/parser.h" /* only needed for GUC variables */ #include "parser/scansup.h" @@ -1211,14 +1212,12 @@ litbufdup(core_yyscan_t yyscanner) static int process_integer_literal(const char *token, YYSTYPE *lval) { - long val; + int val; char *endptr; errno = 0; - val = strtol(token, &endptr, 10); - if (*endptr != '\0' || errno == ERANGE || - /* check for overflow of int */ - val != (int) val) + val = strtoint(token, &endptr, 10); + if (*endptr != '\0' || errno == ERANGE) { /* integer too large, treat it as a float */ lval->str = pstrdup(token); diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 8375b93c39..3f0f65c295 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -22,6 +22,7 @@ #include "access/htup_details.h" #include "access/xact.h" #include "catalog/pg_type.h" +#include "common/string.h" #include "funcapi.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" @@ -251,23 +252,6 @@ static const datetkn *deltacache[MAXDATEFIELDS] = {NULL}; static const datetkn *abbrevcache[MAXDATEFIELDS] = {NULL}; -/* - * strtoint --- just like strtol, but returns int not long - */ -static int -strtoint(const char *nptr, char **endptr, int base) -{ - long val; - - val = strtol(nptr, endptr, base); -#ifdef HAVE_LONG_INT_64 - if (val != (long) ((int32) val)) - errno = ERANGE; -#endif - return (int) val; -} - - /* * Calendar time to Julian date conversions. * Julian date is commonly used in astronomical applications, diff --git a/src/common/string.c b/src/common/string.c index 0e3557076a..a45e9b8858 100644 --- a/src/common/string.c +++ b/src/common/string.c @@ -41,3 +41,18 @@ pg_str_endswith(const char *str, const char *end) str += slen - elen; return strcmp(str, end) == 0; } + + +/* + * strtoint --- just like strtol, but returns int not long + */ +int +strtoint(const char *restrict str, char **restrict endptr, int base) +{ + long val; + + val = strtol(str, endptr, base); + if (val != (int) val) + errno = ERANGE; + return (int) val; +} diff --git a/src/include/common/string.h b/src/include/common/string.h index 06934b9914..23e2e01f0e 100644 --- a/src/include/common/string.h +++ b/src/include/common/string.h @@ -11,5 +11,6 @@ #define COMMON_STRING_H extern bool pg_str_endswith(const char *str, const char *end); +extern int strtoint(const char *restrict str, char **restrict endptr, int base); #endif /* COMMON_STRING_H */ diff --git a/src/interfaces/ecpg/pgtypeslib/Makefile b/src/interfaces/ecpg/pgtypeslib/Makefile index 01206568f1..0945f3d5bc 100644 --- a/src/interfaces/ecpg/pgtypeslib/Makefile +++ b/src/interfaces/ecpg/pgtypeslib/Makefile @@ -32,6 +32,7 @@ SHLIB_EXPORTS = exports.txt OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \ pgstrcasecmp.o \ $(filter rint.o snprintf.o strnlen.o, $(LIBOBJS)) \ + string.o \ $(WIN32RES) all: all-lib @@ -47,6 +48,9 @@ include $(top_srcdir)/src/Makefile.shlib pgstrcasecmp.c rint.c snprintf.c strnlen.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . +string.c: % : $(top_srcdir)/src/common/% + rm -f $@ && $(LN_S) $< . + install: all installdirs install-lib installdirs: installdirs-lib @@ -54,6 +58,6 @@ installdirs: installdirs-lib uninstall: uninstall-lib clean distclean: clean-lib - rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strnlen.c + rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strnlen.c string.c maintainer-clean: distclean maintainer-clean-lib diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c index 24a2f36d4d..6146a3c7b6 100644 --- a/src/interfaces/ecpg/pgtypeslib/interval.c +++ b/src/interfaces/ecpg/pgtypeslib/interval.c @@ -9,25 +9,13 @@ #error -ffast-math is known to break this code #endif +#include "common/string.h" + #include "extern.h" #include "dt.h" #include "pgtypes_error.h" #include "pgtypes_interval.h" -/* copy&pasted from .../src/backend/utils/adt/datetime.c */ -static int -strtoint(const char *nptr, char **endptr, int base) -{ - long val; - - val = strtol(nptr, endptr, base); -#ifdef HAVE_LONG_INT_64 - if (val != (long) ((int32) val)) - errno = ERANGE; -#endif - return (int) val; -} - /* copy&pasted from .../src/backend/utils/adt/datetime.c * and changesd struct pg_tm to struct tm */ diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index ba1798c77e..405dee73b0 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -21,6 +21,8 @@ #include #include +#include "common/string.h" + #include "extern.h" #include "preproc.h" } @@ -727,14 +729,12 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return PARAM; } {integer} { - long val; + int val; char* endptr; errno = 0; - val = strtol((char *)yytext, &endptr,10); - if (*endptr != '\0' || errno == ERANGE || - /* check for overflow of int */ - val != (int) val) + val = strtoint(yytext, &endptr, 10); + if (*endptr != '\0' || errno == ERANGE) { errno = 0; base_yylval.str = mm_strdup(yytext); -- 2.16.2