aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/bootstrap/bootstrap.c4
-rw-r--r--src/backend/catalog/catalog.c20
-rw-r--r--src/backend/commands/tablespace.c16
-rw-r--r--src/backend/libpq/auth.c21
-rw-r--r--src/backend/optimizer/plan/subselect.c3
-rw-r--r--src/backend/parser/gram.y33
-rw-r--r--src/backend/postmaster/postmaster.c7
-rw-r--r--src/backend/utils/adt/cash.c22
-rw-r--r--src/backend/utils/adt/dbsize.c28
-rw-r--r--src/backend/utils/adt/misc.c13
-rw-r--r--src/backend/utils/fmgr/dfmgr.c12
-rw-r--r--src/backend/utils/fmgr/fmgr.c5
-rw-r--r--src/backend/utils/init/miscinit.c8
-rw-r--r--src/backend/utils/misc/guc.c3
-rw-r--r--src/backend/utils/mmgr/mcxt.c49
15 files changed, 97 insertions, 147 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index d23dc4504ae..2a1af63d781 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -249,9 +249,9 @@ AuxiliaryProcessMain(int argc, char *argv[])
case 'd':
{
/* Turn on debugging for the bootstrap process. */
- char *debugstr = palloc(strlen("debug") + strlen(optarg) + 1);
+ char *debugstr;
- sprintf(debugstr, "debug%s", optarg);
+ debugstr = psprintf("debug%s", optarg);
SetConfigOption("log_min_messages", debugstr,
PGC_POSTMASTER, PGC_S_ARGV);
SetConfigOption("client_min_messages", debugstr,
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index c1287a77df0..577206cd26b 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -75,35 +75,23 @@ forkname_to_number(char *forkName)
char *
GetDatabasePath(Oid dbNode, Oid spcNode)
{
- int pathlen;
- char *path;
-
if (spcNode == GLOBALTABLESPACE_OID)
{
/* Shared system relations live in {datadir}/global */
Assert(dbNode == 0);
- pathlen = 6 + 1;
- path = (char *) palloc(pathlen);
- snprintf(path, pathlen, "global");
+ return pstrdup("global");
}
else if (spcNode == DEFAULTTABLESPACE_OID)
{
/* The default tablespace is {datadir}/base */
- pathlen = 5 + OIDCHARS + 1;
- path = (char *) palloc(pathlen);
- snprintf(path, pathlen, "base/%u",
- dbNode);
+ return psprintf("base/%u", dbNode);
}
else
{
/* All other tablespaces are accessed via symlinks */
- pathlen = 9 + 1 + OIDCHARS + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) +
- 1 + OIDCHARS + 1;
- path = (char *) palloc(pathlen);
- snprintf(path, pathlen, "pg_tblspc/%u/%s/%u",
- spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
+ return psprintf("pg_tblspc/%u/%s/%u",
+ spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
}
- return path;
}
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 155eb7c2481..ddc8ec759fc 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -541,12 +541,11 @@ DropTableSpace(DropTableSpaceStmt *stmt)
static void
create_tablespace_directories(const char *location, const Oid tablespaceoid)
{
- char *linkloc = palloc(OIDCHARS + OIDCHARS + 1);
- char *location_with_version_dir = palloc(strlen(location) + 1 +
- strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
+ char *linkloc;
+ char *location_with_version_dir;
- sprintf(linkloc, "pg_tblspc/%u", tablespaceoid);
- sprintf(location_with_version_dir, "%s/%s", location,
+ linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
+ location_with_version_dir = psprintf("%s/%s", location,
TABLESPACE_VERSION_DIRECTORY);
/*
@@ -652,9 +651,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
char *subfile;
struct stat st;
- linkloc_with_version_dir = palloc(9 + 1 + OIDCHARS + 1 +
- strlen(TABLESPACE_VERSION_DIRECTORY));
- sprintf(linkloc_with_version_dir, "pg_tblspc/%u/%s", tablespaceoid,
+ linkloc_with_version_dir = psprintf("pg_tblspc/%u/%s", tablespaceoid,
TABLESPACE_VERSION_DIRECTORY);
/*
@@ -711,8 +708,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
strcmp(de->d_name, "..") == 0)
continue;
- subfile = palloc(strlen(linkloc_with_version_dir) + 1 + strlen(de->d_name) + 1);
- sprintf(subfile, "%s/%s", linkloc_with_version_dir, de->d_name);
+ subfile = psprintf("%s/%s", linkloc_with_version_dir, de->d_name);
/* This check is just to deliver a friendlier error message */
if (!redo && !directory_is_empty(subfile))
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 5b6a71c474c..7e65d2814c5 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -1015,17 +1015,15 @@ pg_GSS_recvauth(Port *port)
*/
if (getenv("KRB5_KTNAME") == NULL)
{
- size_t kt_len = strlen(pg_krb_server_keyfile) + 14;
- char *kt_path = malloc(kt_len);
+ char *kt_path;
- if (!kt_path)
+ if (asprintf(&kt_path, "KRB5_KTNAME=%s", pg_krb_server_keyfile) < 0)
{
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return STATUS_ERROR;
}
- snprintf(kt_path, kt_len, "KRB5_KTNAME=%s", pg_krb_server_keyfile);
putenv(kt_path);
}
}
@@ -1488,8 +1486,7 @@ pg_SSPI_recvauth(Port *port)
char *namebuf;
int retval;
- namebuf = palloc(strlen(accountname) + strlen(domainname) + 2);
- sprintf(namebuf, "%s@%s", accountname, domainname);
+ namebuf = psprintf("%s@%s", accountname, domainname);
retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
pfree(namebuf);
return retval;
@@ -2209,8 +2206,7 @@ CheckLDAPAuth(Port *port)
attributes[0] = port->hba->ldapsearchattribute ? port->hba->ldapsearchattribute : "uid";
attributes[1] = NULL;
- filter = palloc(strlen(attributes[0]) + strlen(port->user_name) + 4);
- sprintf(filter, "(%s=%s)",
+ filter = psprintf("(%s=%s)",
attributes[0],
port->user_name);
@@ -2299,17 +2295,10 @@ CheckLDAPAuth(Port *port)
}
}
else
- {
- fulluser = palloc((port->hba->ldapprefix ? strlen(port->hba->ldapprefix) : 0) +
- strlen(port->user_name) +
- (port->hba->ldapsuffix ? strlen(port->hba->ldapsuffix) : 0) +
- 1);
-
- sprintf(fulluser, "%s%s%s",
+ fulluser = psprintf("%s%s%s",
port->hba->ldapprefix ? port->hba->ldapprefix : "",
port->user_name,
port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
- }
r = ldap_simple_bind_s(ldap, fulluser, passwd);
ldap_unbind(ldap);
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index bafb080d8e4..0df70c4443b 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1119,8 +1119,7 @@ SS_process_ctes(PlannerInfo *root)
root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
/* Label the subplan for EXPLAIN purposes */
- splan->plan_name = palloc(4 + strlen(cte->ctename) + 1);
- sprintf(splan->plan_name, "CTE %s", cte->ctename);
+ splan->plan_name = psprintf("CTE %s", cte->ctename);
/* Lastly, fill in the cost estimates for use later */
cost_subplan(root, splan, plan);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0efe1705e24..363c603848d 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -1450,10 +1450,7 @@ set_rest_more: /* Generic SET syntaxes: */
var_name: ColId { $$ = $1; }
| var_name '.' ColId
- {
- $$ = palloc(strlen($1) + strlen($3) + 2);
- sprintf($$, "%s.%s", $1, $3);
- }
+ { $$ = psprintf("%s.%s", $1, $3); }
;
var_list: var_value { $$ = list_make1($1); }
@@ -10327,15 +10324,7 @@ ConstCharacter: CharacterWithLength
CharacterWithLength: character '(' Iconst ')' opt_charset
{
if (($5 != NULL) && (strcmp($5, "sql_text") != 0))
- {
- char *type;
-
- type = palloc(strlen($1) + 1 + strlen($5) + 1);
- strcpy(type, $1);
- strcat(type, "_");
- strcat(type, $5);
- $1 = type;
- }
+ $1 = psprintf("%s_%s", $1, $5);
$$ = SystemTypeName($1);
$$->typmods = list_make1(makeIntConst($3, @3));
@@ -10346,15 +10335,7 @@ CharacterWithLength: character '(' Iconst ')' opt_charset
CharacterWithoutLength: character opt_charset
{
if (($2 != NULL) && (strcmp($2, "sql_text") != 0))
- {
- char *type;
-
- type = palloc(strlen($1) + 1 + strlen($2) + 1);
- strcpy(type, $1);
- strcat(type, "_");
- strcat(type, $2);
- $1 = type;
- }
+ $1 = psprintf("%s_%s", $1, $2);
$$ = SystemTypeName($1);
@@ -13339,13 +13320,7 @@ doNegateFloat(Value *v)
if (*oldval == '-')
v->val.str = oldval+1; /* just strip the '-' */
else
- {
- char *newval = (char *) palloc(strlen(oldval) + 2);
-
- *newval = '-';
- strcpy(newval+1, oldval);
- v->val.str = newval;
- }
+ v->val.str = psprintf("-%s", oldval);
}
static Node *
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index c9a8a8fc459..98086f78410 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1969,12 +1969,7 @@ retry1:
else
{
/* Append '@' and dbname */
- char *db_user;
-
- db_user = palloc(strlen(port->user_name) +
- strlen(port->database_name) + 2);
- sprintf(db_user, "%s@%s", port->user_name, port->database_name);
- port->user_name = db_user;
+ port->user_name = psprintf("%s@%s", port->user_name, port->database_name);
}
}
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index 82551c5f30e..015875875be 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -377,18 +377,16 @@ cash_out(PG_FUNCTION_ARGS)
* from the value.
*----------
*/
- result = palloc(strlen(bufptr) + strlen(csymbol) + strlen(signsymbol) + 4);
-
switch (sign_posn)
{
case 0:
if (cs_precedes)
- sprintf(result, "(%s%s%s)",
+ result = psprintf("(%s%s%s)",
csymbol,
(sep_by_space == 1) ? " " : "",
bufptr);
else
- sprintf(result, "(%s%s%s)",
+ result = psprintf("(%s%s%s)",
bufptr,
(sep_by_space == 1) ? " " : "",
csymbol);
@@ -396,14 +394,14 @@ cash_out(PG_FUNCTION_ARGS)
case 1:
default:
if (cs_precedes)
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
signsymbol,
(sep_by_space == 2) ? " " : "",
csymbol,
(sep_by_space == 1) ? " " : "",
bufptr);
else
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
signsymbol,
(sep_by_space == 2) ? " " : "",
bufptr,
@@ -412,14 +410,14 @@ cash_out(PG_FUNCTION_ARGS)
break;
case 2:
if (cs_precedes)
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
csymbol,
(sep_by_space == 1) ? " " : "",
bufptr,
(sep_by_space == 2) ? " " : "",
signsymbol);
else
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
bufptr,
(sep_by_space == 1) ? " " : "",
csymbol,
@@ -428,14 +426,14 @@ cash_out(PG_FUNCTION_ARGS)
break;
case 3:
if (cs_precedes)
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
signsymbol,
(sep_by_space == 2) ? " " : "",
csymbol,
(sep_by_space == 1) ? " " : "",
bufptr);
else
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
bufptr,
(sep_by_space == 1) ? " " : "",
signsymbol,
@@ -444,14 +442,14 @@ cash_out(PG_FUNCTION_ARGS)
break;
case 4:
if (cs_precedes)
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
csymbol,
(sep_by_space == 2) ? " " : "",
signsymbol,
(sep_by_space == 1) ? " " : "",
bufptr);
else
- sprintf(result, "%s%s%s%s%s",
+ result = psprintf("%s%s%s%s%s",
bufptr,
(sep_by_space == 1) ? " " : "",
csymbol,
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 868474680df..08ea4570017 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -627,18 +627,14 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
Numeric size = PG_GETARG_NUMERIC(0);
Numeric limit,
limit2;
- char *buf,
- *result;
+ char *result;
limit = int64_to_numeric(10 * 1024);
limit2 = int64_to_numeric(10 * 1024 * 2 - 1);
if (numeric_is_less(size, limit))
{
- buf = numeric_to_cstring(size);
- result = palloc(strlen(buf) + 7);
- strcpy(result, buf);
- strcat(result, " bytes");
+ result = psprintf("%s bytes", numeric_to_cstring(size));
}
else
{
@@ -650,10 +646,7 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
- buf = numeric_to_cstring(size);
- result = palloc(strlen(buf) + 4);
- strcpy(result, buf);
- strcat(result, " kB");
+ result = psprintf("%s kB", numeric_to_cstring(size));
}
else
{
@@ -663,10 +656,7 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
- buf = numeric_to_cstring(size);
- result = palloc(strlen(buf) + 4);
- strcpy(result, buf);
- strcat(result, " MB");
+ result = psprintf("%s MB", numeric_to_cstring(size));
}
else
{
@@ -677,10 +667,7 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
{
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
- buf = numeric_to_cstring(size);
- result = palloc(strlen(buf) + 4);
- strcpy(result, buf);
- strcat(result, " GB");
+ result = psprintf("%s GB", numeric_to_cstring(size));
}
else
{
@@ -688,10 +675,7 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
size = numeric_shift_right(size, 10);
/* size = (size + 1) / 2 */
size = numeric_plus_one_over_two(size);
- buf = numeric_to_cstring(size);
- result = palloc(strlen(buf) + 4);
- strcpy(result, buf);
- strcat(result, " TB");
+ result = psprintf("%s TB", numeric_to_cstring(size));
}
}
}
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index aecdcd056cd..63a991631de 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -242,11 +242,6 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
fctx = palloc(sizeof(ts_db_fctx));
- /*
- * size = tablespace dirname length + dir sep char + oid + terminator
- */
- fctx->location = (char *) palloc(9 + 1 + OIDCHARS + 1 +
- strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
if (tablespaceOid == GLOBALTABLESPACE_OID)
{
fctx->dirdesc = NULL;
@@ -256,9 +251,9 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
else
{
if (tablespaceOid == DEFAULTTABLESPACE_OID)
- sprintf(fctx->location, "base");
+ fctx->location = psprintf("base");
else
- sprintf(fctx->location, "pg_tblspc/%u/%s", tablespaceOid,
+ fctx->location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
TABLESPACE_VERSION_DIRECTORY);
fctx->dirdesc = AllocateDir(fctx->location);
@@ -297,9 +292,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
/* if database subdir is empty, don't report tablespace as used */
- /* size = path length + dir sep char + file name + terminator */
- subdir = palloc(strlen(fctx->location) + 1 + strlen(de->d_name) + 1);
- sprintf(subdir, "%s/%s", fctx->location, de->d_name);
+ subdir = psprintf("%s/%s", fctx->location, de->d_name);
dirdesc = AllocateDir(subdir);
while ((de = ReadDir(dirdesc, subdir)) != NULL)
{
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 562a7c9ab0c..2dd9f750562 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -503,9 +503,7 @@ expand_dynamic_library_name(const char *name)
pfree(full);
}
- new = palloc(strlen(name) + strlen(DLSUFFIX) + 1);
- strcpy(new, name);
- strcat(new, DLSUFFIX);
+ new = psprintf("%s%s", name, DLSUFFIX);
if (!have_slash)
{
@@ -554,7 +552,6 @@ static char *
substitute_libpath_macro(const char *name)
{
const char *sep_ptr;
- char *ret;
AssertArg(name != NULL);
@@ -572,12 +569,7 @@ substitute_libpath_macro(const char *name)
errmsg("invalid macro name in dynamic library path: %s",
name)));
- ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
-
- strcpy(ret, pkglib_path);
- strcat(ret, sep_ptr);
-
- return ret;
+ return psprintf("%s%s", pkglib_path, sep_ptr);
}
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 42de04c60a8..9246a00cbae 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -448,10 +448,7 @@ fetch_finfo_record(void *filehandle, char *funcname)
const Pg_finfo_record *inforec;
static Pg_finfo_record default_inforec = {0};
- /* Compute name of info func */
- infofuncname = (char *) palloc(strlen(funcname) + 10);
- strcpy(infofuncname, "pg_finfo_");
- strcat(infofuncname, funcname);
+ infofuncname = psprintf("pg_finfo_%s", funcname);
/* Try to look up the info function */
infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index ed514f61280..381a629334b 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -165,12 +165,10 @@ make_absolute_path(const char *path)
}
}
- new = malloc(strlen(buf) + strlen(path) + 2);
- if (!new)
+ if (asprintf(&new, "%s/%s", buf, path) < 0)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
- sprintf(new, "%s/%s", buf, path);
free(buf);
}
else
@@ -1286,9 +1284,7 @@ load_libraries(const char *libraries, const char *gucname, bool restricted)
{
char *expanded;
- expanded = palloc(strlen("$libdir/plugins/") + strlen(filename) + 1);
- strcpy(expanded, "$libdir/plugins/");
- strcat(expanded, filename);
+ expanded = psprintf("$libdir/plugins/%s", filename);
pfree(filename);
filename = expanded;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 8db8b3f6ecf..dfc6704fd4d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -7938,8 +7938,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
name = record->name;
/* build new item for array */
- newval = palloc(strlen(name) + 1 + strlen(value) + 1);
- sprintf(newval, "%s=%s", name, value);
+ newval = psprintf("%s=%s", name, value);
datum = CStringGetTextDatum(newval);
if (array)
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 9574fd3c7a3..b7beb130ea3 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -852,3 +852,52 @@ pnstrdup(const char *in, Size len)
out[len] = '\0';
return out;
}
+
+/*
+ * asprintf()-like functions around palloc, adapted from
+ * http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/pkgtools/libnbcompat/files/asprintf.c
+ */
+
+char *
+psprintf(const char *format, ...)
+{
+ va_list ap;
+ char *retval;
+
+ va_start(ap, format);
+ retval = pvsprintf(format, ap);
+ va_end(ap);
+
+ return retval;
+}
+
+char *
+pvsprintf(const char *format, va_list ap)
+{
+ char *buf, *new_buf;
+ size_t len;
+ int retval;
+ va_list ap2;
+
+ len = 128;
+ buf = palloc(len);
+
+ va_copy(ap2, ap);
+ retval = vsnprintf(buf, len, format, ap);
+ Assert(retval >= 0);
+
+ if (retval < len)
+ {
+ new_buf = repalloc(buf, retval + 1);
+ va_end(ap2);
+ return new_buf;
+ }
+
+ len = (size_t)retval + 1;
+ pfree(buf);
+ buf = palloc(len);
+ retval = vsnprintf(buf, len, format, ap2);
+ va_end(ap2);
+ Assert(retval == len - 1);
+ return buf;
+}