diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml
index e2e9909..d60d4ff 100644
*** a/doc/src/sgml/ref/postgres-ref.sgml
--- b/doc/src/sgml/ref/postgres-ref.sgml
*************** PostgreSQL documentation
*** 529,535 ****
      </indexterm>
  
      <para>
!      The following options only apply to the single-user mode.
      </para>
  
      <variablelist>
--- 529,537 ----
      </indexterm>
  
      <para>
!      The following options only apply to the single-user mode
!      (see <xref linkend="app-postgres-single-user"
!      endterm="app-postgres-single-user-title">).
      </para>
  
      <variablelist>
*************** PostgreSQL documentation
*** 558,564 ****
        <term><option>-E</option></term>
        <listitem>
         <para>
!         Echo all commands.
         </para>
        </listitem>
       </varlistentry>
--- 560,566 ----
        <term><option>-E</option></term>
        <listitem>
         <para>
!         Echo all commands to standard output before executing them.
         </para>
        </listitem>
       </varlistentry>
*************** PostgreSQL documentation
*** 567,573 ****
        <term><option>-j</option></term>
        <listitem>
         <para>
!         Disables use of newline as a statement delimiter.
         </para>
        </listitem>
       </varlistentry>
--- 569,576 ----
        <term><option>-j</option></term>
        <listitem>
         <para>
!         Use semicolon followed by two newlines, rather than just newline,
!         as the command entry terminator.
         </para>
        </listitem>
       </varlistentry>
*************** PostgreSQL documentation
*** 760,767 ****
    </para>
   </refsect1>
  
!  <refsect1>
!   <title>Usage</title>
  
     <para>
      To start a single-user mode server, use a command like
--- 763,770 ----
    </para>
   </refsect1>
  
!  <refsect1 id="app-postgres-single-user">
!   <title id="app-postgres-single-user-title">Single-User Mode</title>
  
     <para>
      To start a single-user mode server, use a command like
*************** PostgreSQL documentation
*** 778,807 ****
      entry terminator; there is no intelligence about semicolons,
      as there is in <application>psql</>.  To continue a command
      across multiple lines, you must type backslash just before each
!     newline except the last one.
     </para>
  
     <para>
!     But if you use the <option>-j</> command line switch, then newline does
!     not terminate command entry.  In this case, the server will read the standard input
!     until the end-of-file (<acronym>EOF</>) marker, then
!     process the input as a single command string.  Backslash-newline is not
!     treated specially in this case.
     </para>
  
     <para>
      To quit the session, type <acronym>EOF</acronym>
      (<keycombo action="simul"><keycap>Control</><keycap>D</></>, usually).
!     If you've
!     used <option>-j</>, two consecutive <acronym>EOF</>s are needed to exit.
     </para>
  
     <para>
      Note that the single-user mode server does not provide sophisticated
      line-editing features (no command history, for example).
!     Single-User mode also does not do any background processing, like
!     automatic checkpoints.
! 
     </para>
   </refsect1>
  
--- 781,820 ----
      entry terminator; there is no intelligence about semicolons,
      as there is in <application>psql</>.  To continue a command
      across multiple lines, you must type backslash just before each
!     newline except the last one.  The backslash and adjacent newline are
!     both dropped from the input command.  Note that this will happen even
!     when within a string literal or comment.
     </para>
  
     <para>
!     But if you use the <option>-j</> command line switch, a single newline
!     does not terminate command entry; instead, the sequence
!     semicolon-newline-newline does.  That is, type a semicolon immediately
!     followed by a completely empty line.  Backslash-newline is not
!     treated specially in this mode.  Again, there is no intelligence about
!     such a sequence appearing within a string literal or comment.
!    </para>
! 
!    <para>
!     In either input mode, if you type a semicolon that is not just before or
!     part of a command entry terminator, it is considered a command separator.
!     When you do type a command entry terminator, the multiple statements
!     you've entered will be executed as a single transaction.
     </para>
  
     <para>
      To quit the session, type <acronym>EOF</acronym>
      (<keycombo action="simul"><keycap>Control</><keycap>D</></>, usually).
!     If you've entered any text since the last command entry terminator,
!     then <acronym>EOF</acronym> will be taken as a command entry terminator,
!     and another <acronym>EOF</> will be needed to exit.
     </para>
  
     <para>
      Note that the single-user mode server does not provide sophisticated
      line-editing features (no command history, for example).
!     Single-user mode also does not do any background processing, such as
!     automatic checkpoints or replication.
     </para>
   </refsect1>
  
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index 6e1b241..2239859 100644
*** a/src/backend/catalog/information_schema.sql
--- b/src/backend/catalog/information_schema.sql
***************
*** 5,10 ****
--- 5,18 ----
   * Copyright (c) 2003-2015, PostgreSQL Global Development Group
   *
   * src/backend/catalog/information_schema.sql
+  *
+  * Note: this file is read in single-user -j mode, which means that the
+  * command terminator is semicolon-newline-newline; whenever the backend
+  * sees that, it stops and executes what it's got.  If you write a lot of
+  * statements without empty lines between, they'll all get quoted to you
+  * in any error message about one of them, so don't do that.  Also, you
+  * cannot write a semicolon immediately followed by an empty line in a
+  * string literal (including a function body!) or a multiline comment.
   */
  
  /*
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ccc030f..536c805 100644
*** a/src/backend/catalog/system_views.sql
--- b/src/backend/catalog/system_views.sql
***************
*** 4,9 ****
--- 4,17 ----
   * Copyright (c) 1996-2015, PostgreSQL Global Development Group
   *
   * src/backend/catalog/system_views.sql
+  *
+  * Note: this file is read in single-user -j mode, which means that the
+  * command terminator is semicolon-newline-newline; whenever the backend
+  * sees that, it stops and executes what it's got.  If you write a lot of
+  * statements without empty lines between, they'll all get quoted to you
+  * in any error message about one of them, so don't do that.  Also, you
+  * cannot write a semicolon immediately followed by an empty line in a
+  * string literal (including a function body!) or a multiline comment.
   */
  
  CREATE VIEW pg_roles AS
diff --git a/src/backend/snowball/snowball.sql.in b/src/backend/snowball/snowball.sql.in
index 2f68393..68363f1 100644
*** a/src/backend/snowball/snowball.sql.in
--- b/src/backend/snowball/snowball.sql.in
***************
*** 1,6 ****
! -- src/backend/snowball/snowball.sql.in$
  
- -- text search configuration for _LANGNAME_ language
  CREATE TEXT SEARCH DICTIONARY _DICTNAME_
  	(TEMPLATE = snowball, Language = _LANGNAME_ _STOPWORDS_);
  
--- 1,22 ----
! /*
!  * text search configuration for _LANGNAME_ language
!  *
!  * Copyright (c) 2007-2015, PostgreSQL Global Development Group
!  *
!  * src/backend/snowball/snowball.sql.in
!  *
!  * _LANGNAME_ and certain other macros are replaced for each language;
!  * see the Makefile for details.
!  *
!  * Note: this file is read in single-user -j mode, which means that the
!  * command terminator is semicolon-newline-newline; whenever the backend
!  * sees that, it stops and executes what it's got.  If you write a lot of
!  * statements without empty lines between, they'll all get quoted to you
!  * in any error message about one of them, so don't do that.  Also, you
!  * cannot write a semicolon immediately followed by an empty line in a
!  * string literal (including a function body!) or a multiline comment.
!  */
  
  CREATE TEXT SEARCH DICTIONARY _DICTNAME_
  	(TEMPLATE = snowball, Language = _LANGNAME_ _STOPWORDS_);
  
diff --git a/src/backend/snowball/snowball_func.sql.in b/src/backend/snowball/snowball_func.sql.in
index e7d4510..debb0e0 100644
*** a/src/backend/snowball/snowball_func.sql.in
--- b/src/backend/snowball/snowball_func.sql.in
***************
*** 1,4 ****
! -- src/backend/snowball/snowball_func.sql.in$
  
  SET search_path = pg_catalog;
  
--- 1,21 ----
! /*
!  * Create underlying C functions for Snowball stemmers
!  *
!  * Copyright (c) 2007-2015, PostgreSQL Global Development Group
!  *
!  * src/backend/snowball/snowball_func.sql.in
!  *
!  * This file is combined with multiple instances of snowball.sql.in to
!  * build snowball_create.sql, which is executed during initdb.
!  *
!  * Note: this file is read in single-user -j mode, which means that the
!  * command terminator is semicolon-newline-newline; whenever the backend
!  * sees that, it stops and executes what it's got.  If you write a lot of
!  * statements without empty lines between, they'll all get quoted to you
!  * in any error message about one of them, so don't do that.  Also, you
!  * cannot write a semicolon immediately followed by an empty line in a
!  * string literal (including a function body!) or a multiline comment.
!  */
  
  SET search_path = pg_catalog;
  
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1dc2eb0..4ae2548 100644
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
*************** static CachedPlanSource *unnamed_stmt_ps
*** 157,174 ****
  
  /* assorted command-line switches */
  static const char *userDoption = NULL;	/* -D switch */
- 
  static bool EchoQuery = false;	/* -E switch */
! 
! /*
!  * people who want to use EOF should #define DONTUSENEWLINE in
!  * tcop/tcopdebug.h
!  */
! #ifndef TCOP_DONTUSENEWLINE
! static int	UseNewLine = 1;		/* Use newlines query delimiters (the default) */
! #else
! static int	UseNewLine = 0;		/* Use EOF as query delimiters */
! #endif   /* TCOP_DONTUSENEWLINE */
  
  /* whether or not, and why, we were canceled by conflict with recovery */
  static bool RecoveryConflictPending = false;
--- 157,164 ----
  
  /* assorted command-line switches */
  static const char *userDoption = NULL;	/* -D switch */
  static bool EchoQuery = false;	/* -E switch */
! static bool UseSemiNewlineNewline = false;		/* -j switch */
  
  /* whether or not, and why, we were canceled by conflict with recovery */
  static bool RecoveryConflictPending = false;
*************** static int
*** 219,226 ****
  InteractiveBackend(StringInfo inBuf)
  {
  	int			c;				/* character read from getc() */
- 	bool		end = false;	/* end-of-input flag */
- 	bool		backslashSeen = false;	/* have we seen a \ ? */
  
  	/*
  	 * display a prompt and obtain input from the user
--- 209,214 ----
*************** InteractiveBackend(StringInfo inBuf)
*** 230,284 ****
  
  	resetStringInfo(inBuf);
  
! 	if (UseNewLine)
  	{
! 		/*
! 		 * if we are using \n as a delimiter, then read characters until the
! 		 * \n.
! 		 */
! 		while ((c = interactive_getc()) != EOF)
  		{
! 			if (c == '\n')
  			{
! 				if (backslashSeen)
  				{
  					/* discard backslash from inBuf */
  					inBuf->data[--inBuf->len] = '\0';
! 					backslashSeen = false;
  					continue;
  				}
  				else
  				{
! 					/* keep the newline character */
  					appendStringInfoChar(inBuf, '\n');
  					break;
  				}
  			}
- 			else if (c == '\\')
- 				backslashSeen = true;
- 			else
- 				backslashSeen = false;
- 
- 			appendStringInfoChar(inBuf, (char) c);
  		}
  
! 		if (c == EOF)
! 			end = true;
! 	}
! 	else
! 	{
! 		/*
! 		 * otherwise read characters until EOF.
! 		 */
! 		while ((c = interactive_getc()) != EOF)
! 			appendStringInfoChar(inBuf, (char) c);
! 
! 		/* No input before EOF signal means time to quit. */
! 		if (inBuf->len == 0)
! 			end = true;
  	}
  
! 	if (end)
  		return EOF;
  
  	/*
--- 218,273 ----
  
  	resetStringInfo(inBuf);
  
! 	/*
! 	 * Read characters until EOF or the appropriate delimiter is seen.
! 	 */
! 	while ((c = interactive_getc()) != EOF)
  	{
! 		if (c == '\n')
  		{
! 			if (UseSemiNewlineNewline)
  			{
! 				/*
! 				 * In -j mode, semicolon followed by two newlines ends the
! 				 * command; otherwise treat newline as regular character.
! 				 */
! 				if (inBuf->len > 1 &&
! 					inBuf->data[inBuf->len - 1] == '\n' &&
! 					inBuf->data[inBuf->len - 2] == ';')
! 				{
! 					/* might as well drop the second newline */
! 					break;
! 				}
! 			}
! 			else
! 			{
! 				/*
! 				 * In plain mode, newline ends the command unless preceded by
! 				 * backslash.
! 				 */
! 				if (inBuf->len > 0 &&
! 					inBuf->data[inBuf->len - 1] == '\\')
  				{
  					/* discard backslash from inBuf */
  					inBuf->data[--inBuf->len] = '\0';
! 					/* discard newline too */
  					continue;
  				}
  				else
  				{
! 					/* keep the newline character, but end the command */
  					appendStringInfoChar(inBuf, '\n');
  					break;
  				}
  			}
  		}
  
! 		/* Not newline, or newline treated as regular character */
! 		appendStringInfoChar(inBuf, (char) c);
  	}
  
! 	/* No input before EOF signal means time to quit. */
! 	if (c == EOF && inBuf->len == 0)
  		return EOF;
  
  	/*
*************** process_postgres_switches(int argc, char
*** 3391,3397 ****
  
  			case 'j':
  				if (secure)
! 					UseNewLine = 0;
  				break;
  
  			case 'k':
--- 3380,3386 ----
  
  			case 'j':
  				if (secure)
! 					UseSemiNewlineNewline = true;
  				break;
  
  			case 'k':
diff --git a/src/include/tcop/tcopdebug.h b/src/include/tcop/tcopdebug.h
index d7145ce..e69de29 100644
*** a/src/include/tcop/tcopdebug.h
--- b/src/include/tcop/tcopdebug.h
***************
*** 1,44 ****
- /*-------------------------------------------------------------------------
-  *
-  * tcopdebug.h
-  *	  #defines governing debugging behaviour in the traffic cop
-  *
-  *
-  * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
-  * Portions Copyright (c) 1994, Regents of the University of California
-  *
-  * src/include/tcop/tcopdebug.h
-  *
-  *-------------------------------------------------------------------------
-  */
- #ifndef TCOPDEBUG_H
- #define TCOPDEBUG_H
- 
- /* ----------------------------------------------------------------
-  *		debugging defines.
-  *
-  *		If you want certain debugging behaviour, then #define
-  *		the variable to 1, else #undef it. -cim 10/26/89
-  * ----------------------------------------------------------------
-  */
- 
- /* ----------------
-  *		TCOP_SHOWSTATS controls whether or not buffer and
-  *		access method statistics are shown for each query.  -cim 2/9/89
-  * ----------------
-  */
- #undef TCOP_SHOWSTATS
- 
- /* ----------------
-  *		TCOP_DONTUSENEWLINE controls the default setting of
-  *		the UseNewLine variable in postgres.c
-  * ----------------
-  */
- #undef TCOP_DONTUSENEWLINE
- 
- /* ----------------------------------------------------------------
-  *		#defines controlled by above definitions
-  * ----------------------------------------------------------------
-  */
- 
- #endif   /* TCOPDEBUG_H */
--- 0 ----
