src/bin/pg_dump/dumputils.c
static bool
parseAclItem(const char *item, const char *type,
			 const char *name, const char *subname, int remoteVersion,
			 PQExpBuffer grantee, PQExpBuffer grantor,
			 PQExpBuffer privs, PQExpBuffer privswgo)
{
	char	   *buf;
	bool		all_with_go = true;
	bool		all_without_go = true;
	char	   *eqpos;
	char	   *slpos;
	char	   *pos;

	buf = pg_strdup(item);

	/* user or group name is string up to = */
	eqpos = dequoteAclUserName(grantee, buf);
	if (*eqpos != '=')
	{
		pg_free(buf);
		return false;
	}

	/* grantor should appear after / */
	slpos = strchr(eqpos + 1, '/');
	if (slpos)
	{
		*slpos++ = '\0';
		slpos = dequoteAclUserName(grantor, slpos);
		if (*slpos != '\0')
		{
			pg_free(buf);
			return false;
		}
	}
	else
	{
		pg_free(buf);
		return false;
	}

	/* privilege codes */
#define CONVERT_PRIV(code, keywd) \
do { \
	if ((pos = strchr(eqpos + 1, code))) \
	{ \
		if (*(pos + 1) == '*' && privswgo != NULL) \
		{ \
			AddAcl(privswgo, keywd, subname); \
			all_without_go = false; \
		} \
		else \
		{ \
			AddAcl(privs, keywd, subname); \
			all_with_go = false; \
		} \
	} \
	else \
		all_with_go = all_without_go = false; \
} while (0)

	resetPQExpBuffer(privs);
	resetPQExpBuffer(privswgo);

	if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 ||
		strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0)
	{
		CONVERT_PRIV('r', "SELECT");

		if (strcmp(type, "SEQUENCE") == 0 ||
			strcmp(type, "SEQUENCES") == 0)
			/* sequence only */
			CONVERT_PRIV('U', "USAGE");
		else
		{
			/* table only */
			CONVERT_PRIV('a', "INSERT");
			CONVERT_PRIV('x', "REFERENCES");
			/* rest are not applicable to columns */
			if (subname == NULL)
			{
				CONVERT_PRIV('d', "DELETE");
				CONVERT_PRIV('t', "TRIGGER");
				CONVERT_PRIV('D', "TRUNCATE");
			}
		}

		/* UPDATE */
		CONVERT_PRIV('w', "UPDATE");
	}
	else if (strcmp(type, "FUNCTION") == 0 ||
			 strcmp(type, "FUNCTIONS") == 0)
		CONVERT_PRIV('X', "EXECUTE");
	else if (strcmp(type, "PROCEDURE") == 0 ||
			 strcmp(type, "PROCEDURES") == 0)
		CONVERT_PRIV('X', "EXECUTE");
	else if (strcmp(type, "LANGUAGE") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "SCHEMA") == 0 ||
			 strcmp(type, "SCHEMAS") == 0)
	{
		CONVERT_PRIV('C', "CREATE");
		CONVERT_PRIV('U', "USAGE");
	}
	else if (strcmp(type, "DATABASE") == 0)
	{
		CONVERT_PRIV('C', "CREATE");
		CONVERT_PRIV('c', "CONNECT");
		CONVERT_PRIV('T', "TEMPORARY");
	}
	else if (strcmp(type, "TABLESPACE") == 0)
		CONVERT_PRIV('C', "CREATE");
	else if (strcmp(type, "TYPE") == 0 ||
			 strcmp(type, "TYPES") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN SERVER") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN TABLE") == 0)
		CONVERT_PRIV('r', "SELECT");
	else if (strcmp(type, "LARGE OBJECT") == 0)
	{
		CONVERT_PRIV('r', "SELECT");
		CONVERT_PRIV('w', "UPDATE");
	}
	else
		abort();

#undef CONVERT_PRIV

	if (all_with_go)
	{
		resetPQExpBuffer(privs);
		printfPQExpBuffer(privswgo, "ALL");
		if (subname)
			appendPQExpBuffer(privswgo, "(%s)", subname);
	}
	else if (all_without_go)
	{
		resetPQExpBuffer(privswgo);
		printfPQExpBuffer(privs, "ALL");
		if (subname)
			appendPQExpBuffer(privs, "(%s)", subname);
	}

	pg_free(buf);

	return true;
}
/*
 * This will parse an aclitem string, having the general form
 *		username=privilegecodes/grantor
 *
 * Returns true on success, false on parse error.  On success, the components
 * of the string are returned in the PQExpBuffer parameters.
 *
 * The returned grantee string will be the dequoted username, or an empty
 * string in the case of a grant to PUBLIC.  The returned grantor is the
 * dequoted grantor name.  Privilege characters are translated to GRANT/REVOKE
 * comma-separated privileges lists.  If "privswgo" is non-NULL, the result is
 * separate lists for privileges with grant option ("privswgo") and without
 * ("privs").  Otherwise, "privs" bears every relevant privilege, ignoring the
 * grant option distinction.
 *
 * Note: for cross-version compatibility, it's important to use ALL to
 * represent the privilege sets whenever appropriate.
 */
This will parse an aclitem string, having the general form
username=privilegecodes/grantor

Returns true on success, false on parse error.  On success, the components
of the string are returned in the PQExpBuffer parameters.

The returned grantee string will be the dequoted username, or an empty
string in the case of a grant to PUBLIC.  The returned grantor is the
dequoted grantor name.  Privilege characters are translated to GRANT/REVOKE
comma-separated privileges lists.

for cross-version compatibility, it's important to use ALL to
represent the privilege sets whenever appropriate.
This will parse an aclitem string having the general form username = privilegecodes / grantor Returns true on success false on parse error . On success the components of the string are returned in the PQExpBuffer parameters . The returned grantee string will be the dequoted username or an empty string in the case of a grant to PUBLIC . The returned grantor is the dequoted grantor name . Privilege characters are translated to GRANT / REVOKE comma - separated privileges lists . for cross - version compatibility it ' s important to use ALL to represent the privilege sets whenever appropriate .
static bool
parseAclItem(const char *item, const char *type,
			 const char *name, const char *subname, int remoteVersion,
			 PQExpBuffer grantee, PQExpBuffer grantor,
			 PQExpBuffer privs, PQExpBuffer privswgo)
{
	char	   *buf;
	bool		all_with_go = true;
	bool		all_without_go = true;
	char	   *eqpos;
	char	   *slpos;
	char	   *pos;
	buf = pg_strdup(item);
	eqpos = dequoteAclUserName(grantee, buf);
	if (*eqpos != '=')
	{
		pg_free(buf);
		return false;
	}
	slpos = strchr(eqpos + 1, '/');
	if (slpos)
	{
		*slpos++ = '\0';
		slpos = dequoteAclUserName(grantor, slpos);
		if (*slpos != '\0')
		{
			pg_free(buf);
			return false;
		}
	}
	else
	{
		pg_free(buf);
		return false;
	}
#define CONVERT_PRIV(code, keywd) \
do { \
	if ((pos = strchr(eqpos + 1, code))) \
	{ \
		if (*(pos + 1) == '*' && privswgo != NULL) \
		{ \
			AddAcl(privswgo, keywd, subname); \
			all_without_go = false; \
		} \
		else \
		{ \
			AddAcl(privs, keywd, subname); \
			all_with_go = false; \
		} \
	} \
	else \
		all_with_go = all_without_go = false; \
} while (0)
	resetPQExpBuffer(privs);
	resetPQExpBuffer(privswgo);
	if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 ||
		strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0)
	{
		CONVERT_PRIV('r', "SELECT");
		if (strcmp(type, "SEQUENCE") == 0 ||
			strcmp(type, "SEQUENCES") == 0)
			CONVERT_PRIV('U', "USAGE");
		else
		{
			CONVERT_PRIV('a', "INSERT");
			CONVERT_PRIV('x', "REFERENCES");
			if (subname == NULL)
			{
				CONVERT_PRIV('d', "DELETE");
				CONVERT_PRIV('t', "TRIGGER");
				CONVERT_PRIV('D', "TRUNCATE");
			}
		}
		CONVERT_PRIV('w', "UPDATE");
	}
	else if (strcmp(type, "FUNCTION") == 0 ||
			 strcmp(type, "FUNCTIONS") == 0)
		CONVERT_PRIV('X', "EXECUTE");
	else if (strcmp(type, "PROCEDURE") == 0 ||
			 strcmp(type, "PROCEDURES") == 0)
		CONVERT_PRIV('X', "EXECUTE");
	else if (strcmp(type, "LANGUAGE") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "SCHEMA") == 0 ||
			 strcmp(type, "SCHEMAS") == 0)
	{
		CONVERT_PRIV('C', "CREATE");
		CONVERT_PRIV('U', "USAGE");
	}
	else if (strcmp(type, "DATABASE") == 0)
	{
		CONVERT_PRIV('C', "CREATE");
		CONVERT_PRIV('c', "CONNECT");
		CONVERT_PRIV('T', "TEMPORARY");
	}
	else if (strcmp(type, "TABLESPACE") == 0)
		CONVERT_PRIV('C', "CREATE");
	else if (strcmp(type, "TYPE") == 0 ||
			 strcmp(type, "TYPES") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN SERVER") == 0)
		CONVERT_PRIV('U', "USAGE");
	else if (strcmp(type, "FOREIGN TABLE") == 0)
		CONVERT_PRIV('r', "SELECT");
	else if (strcmp(type, "LARGE OBJECT") == 0)
	{
		CONVERT_PRIV('r', "SELECT");
		CONVERT_PRIV('w', "UPDATE");
	}
	else
		abort();
#undef CONVERT_PRIV
	if (all_with_go)
	{
		resetPQExpBuffer(privs);
		printfPQExpBuffer(privswgo, "ALL");
		if (subname)
			appendPQExpBuffer(privswgo, "(%s)", subname);
	}
	else if (all_without_go)
	{
		resetPQExpBuffer(privswgo);
		printfPQExpBuffer(privs, "ALL");
		if (subname)
			appendPQExpBuffer(privs, "(%s)", subname);
	}
	pg_free(buf);
	return true;
}
static bool parseAclItem ( const char * item , const char * type , const char * name , const char * subname , int remoteVersion , PQExpBuffer grantee , PQExpBuffer grantor , PQExpBuffer privs , PQExpBuffer privswgo ) { char * buf ; bool all_with_go = true ; bool all_without_go = true ; char * eqpos ; char * slpos ; char * pos ; buf = pg_strdup ( item ) ; eqpos = dequoteAclUserName ( grantee , buf ) ; if ( * eqpos != ' ' ) { pg_free ( buf ) ; return false ; } slpos = strchr ( eqpos + 1 , ' ' ) ; if ( slpos ) { * slpos ++ = ' \0 ' ; slpos = dequoteAclUserName ( grantor , slpos ) ; if ( * slpos != ' \0 ' ) { pg_free ( buf ) ; return false ; } } else { pg_free ( buf ) ; return false ; } #define CONVERT_PRIV ( code , keywd )  \
do { \
	if ((pos = strchr(eqpos + 1, code))) \
	{ \
		if (*(pos + 1) == '*' && privswgo != NULL) \
		{ \
			AddAcl(privswgo, keywd, subname); \
			all_without_go = false; \
		} \
		else \
		{ \
			AddAcl(privs, keywd, subname); \
			all_with_go = false; \
		} \
	} \
	else \
		all_with_go = all_without_go = false; \
} while (0) resetPQExpBuffer ( privs ) ; resetPQExpBuffer ( privswgo ) ; if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) { CONVERT_PRIV ( ' ' , " " ) ; if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else { CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; if ( subname == NULL ) { CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; } } CONVERT_PRIV ( ' ' , " " ) ; } else if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) { CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; } else if ( strcmp ( type , " " ) == 0 ) { CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; } else if ( strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 || strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 ) CONVERT_PRIV ( ' ' , " " ) ; else if ( strcmp ( type , " " ) == 0 ) { CONVERT_PRIV ( ' ' , " " ) ; CONVERT_PRIV ( ' ' , " " ) ; } else abort ( ) ; #undef  CONVERT_PRIV if ( all_with_go ) { resetPQExpBuffer ( privs ) ; printfPQExpBuffer ( privswgo , " " ) ; if ( subname ) appendPQExpBuffer ( privswgo , " " , subname ) ; } else if ( all_without_go ) { resetPQExpBuffer ( privswgo ) ; printfPQExpBuffer ( privs , " " ) ; if ( subname ) appendPQExpBuffer ( privs , " " , subname ) ; } pg_free ( buf ) ; return true ; }
This will parse an aclitem string, having the general form
              username=privilegecodes/grantor
This will parse an aclitem string having the general form username = privilegecodes / grantor
/* user or group name is string up to = */ /* grantor should appear after / */ /* privilege codes */ /* sequence only */ /* table only */ /* rest are not applicable to columns */ /* UPDATE */