diff -c -r pgsql.00/src/backend/utils/misc/guc.c psql.01/src/backend/utils/misc/guc.c
*** pgsql.00/src/backend/utils/misc/guc.c	2005-06-28 07:09:00.000000000 +0200
--- psql.01/src/backend/utils/misc/guc.c	2005-07-03 16:59:29.000000000 +0200
***************
*** 157,163 ****
  char	   *HbaFileName;
  char	   *IdentFileName;
  char	   *external_pid_file;
! 
  
  /*
   * These variables are all dummies that don't do anything, except in some
--- 157,163 ----
  char	   *HbaFileName;
  char	   *IdentFileName;
  char	   *external_pid_file;
! bool 	trace_plpgsql;
  
  /*
   * These variables are all dummies that don't do anything, except in some
***************
*** 530,535 ****
--- 530,544 ----
  		false, NULL, NULL
  	},
  	{
+ 		{"trace_plpgsql", PGC_USERSET, DEVELOPER_OPTIONS,
+ 			gettext_noop("Set tracing off on plpgsql functions."),
+ 			NULL,
+ 			GUC_NOT_IN_SAMPLE
+ 		},
+ 		&trace_plpgsql,
+ 		false, NULL, NULL
+ 	},
+ 	{
  		{"log_duration", PGC_SUSET, LOGGING_WHAT,
  			gettext_noop("Logs the duration of each completed SQL statement."),
  			NULL
diff -c -r pgsql.00/src/bin/psql/command.c psql.01/src/bin/psql/command.c
*** pgsql.00/src/bin/psql/command.c	2005-06-13 08:36:00.000000000 +0200
--- psql.01/src/bin/psql/command.c	2005-07-03 20:13:37.000000000 +0200
***************
*** 1015,1020 ****
--- 1015,1021 ----
  	}
  
  	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
+ 	PQsetTraceProcessor(pset.db, traceProcessor);
  
  	/* Update variables */
  	SyncVariables();
diff -c -r pgsql.00/src/bin/psql/common.c psql.01/src/bin/psql/common.c
*** pgsql.00/src/bin/psql/common.c	2005-06-22 23:14:00.000000000 +0200
--- psql.01/src/bin/psql/common.c	2005-07-03 20:35:45.000000000 +0200
***************
*** 34,39 ****
--- 34,40 ----
  #include "print.h"
  #include "mainloop.h"
  #include "mb/pg_wchar.h"
+ #include "input.h"
  
  
  /* Workarounds for Windows */
***************
*** 64,69 ****
--- 65,72 ----
  
  static bool command_no_begin(const char *query);
  
+ void traceProcessor(char **cmd, char **varname, char **expr);
+ 
  /*
   * "Safe" wrapper around strdup()
   */
***************
*** 216,221 ****
--- 219,235 ----
  }
  
  
+ void traceProcessor(char **cmd, char **varname, char **expr)
+ {
+     *expr = NULL;
+     *varname = NULL;
+     
+     *cmd = gets_interactive("dbg. ");
+     if (cmd)
+ 	if (strcmp(*cmd, "p") == 0)
+ 	    *varname = gets_interactive("var-. ");
+ 
+ }
  
  /*
   * Code to support query cancellation
diff -c -r pgsql.00/src/bin/psql/common.h psql.01/src/bin/psql/common.h
*** pgsql.00/src/bin/psql/common.h	2005-06-13 08:36:00.000000000 +0200
--- psql.01/src/bin/psql/common.h	2005-07-03 20:15:42.000000000 +0200
***************
*** 40,45 ****
--- 40,46 ----
  __attribute__((format(printf, 1, 2)));
  
  extern void NoticeProcessor(void *arg, const char *message);
+ extern void traceProcessor(char **cmd, char **varname, char **expr);
  
  extern volatile bool cancel_pressed;
  
diff -c -r pgsql.00/src/bin/psql/startup.c psql.01/src/bin/psql/startup.c
*** pgsql.00/src/bin/psql/startup.c	2005-06-21 06:02:00.000000000 +0200
--- psql.01/src/bin/psql/startup.c	2005-07-03 20:14:13.000000000 +0200
***************
*** 221,226 ****
--- 221,227 ----
  	}
  
  	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
+ 	PQsetTraceProcessor(pset.db, traceProcessor);
  
  	SyncVariables();
  
diff -c -r pgsql.00/src/include/utils/guc.h psql.01/src/include/utils/guc.h
*** pgsql.00/src/include/utils/guc.h	2005-06-26 05:04:00.000000000 +0200
--- psql.01/src/include/utils/guc.h	2005-07-03 16:50:04.000000000 +0200
***************
*** 133,139 ****
  extern char *HbaFileName;
  extern char *IdentFileName;
  extern char *external_pid_file;
! 
  
  extern void SetConfigOption(const char *name, const char *value,
  				GucContext context, GucSource source);
--- 133,139 ----
  extern char *HbaFileName;
  extern char *IdentFileName;
  extern char *external_pid_file;
! extern bool trace_plpgsql;
  
  extern void SetConfigOption(const char *name, const char *value,
  				GucContext context, GucSource source);
diff -c -r pgsql.00/src/interfaces/libpq/fe-connect.c psql.01/src/interfaces/libpq/fe-connect.c
*** pgsql.00/src/interfaces/libpq/fe-connect.c	2005-06-27 04:04:00.000000000 +0200
--- psql.01/src/interfaces/libpq/fe-connect.c	2005-07-03 20:30:17.000000000 +0200
***************
*** 202,208 ****
  	}
  };
  
- 
  static bool connectOptions1(PGconn *conn, const char *conninfo);
  static bool connectOptions2(PGconn *conn);
  static int	connectDBStart(PGconn *conn);
--- 202,207 ----
***************
*** 216,221 ****
--- 215,221 ----
  				const char *keyword);
  static void defaultNoticeReceiver(void *arg, const PGresult *res);
  static void defaultNoticeProcessor(void *arg, const char *message);
+ static void defaultTraceProcessor(char **cmd, char **varname, char **expr);
  static int parseServiceInfo(PQconninfoOption *options,
  				 PQExpBuffer errorMessage);
  static char *pwdfMatchesString(char *buf, char *token);
***************
*** 1825,1830 ****
--- 1825,1831 ----
  	/* Zero all pointers and booleans */
  	MemSet(conn, 0, sizeof(PGconn));
  
+ 	conn->traceProc = defaultTraceProcessor;
  	conn->noticeHooks.noticeRec = defaultNoticeReceiver;
  	conn->noticeHooks.noticeProc = defaultNoticeProcessor;
  	conn->status = CONNECTION_BAD;
***************
*** 3024,3029 ****
--- 3025,3055 ----
  	fprintf(stderr, "%s", message);
  }
  
+ 
+ static void
+ defaultTraceProcessor(char **cmd, char **varname, char **expr)
+ {
+     *cmd = strdup("c");
+     *varname = NULL;
+     *expr = NULL;
+ }
+ 
+ PQtraceProcessor
+ PQsetTraceProcessor(PGconn *conn, PQtraceProcessor proc)
+ {
+ 	PQtraceProcessor old;
+ 
+ 	if (conn == NULL)
+ 		return NULL;
+ 
+ 	old = conn->traceProc;
+ 	if (proc)
+ 	{
+ 		conn->traceProc = proc;
+ 	}
+ 	return old;
+ }
+ 
  /*
   * returns a pointer to the next token or NULL if the current
   * token doesn't match
diff -c -r pgsql.00/src/interfaces/libpq/fe-protocol3.c psql.01/src/interfaces/libpq/fe-protocol3.c
*** pgsql.00/src/interfaces/libpq/fe-protocol3.c	2005-06-12 02:00:00.000000000 +0200
--- psql.01/src/interfaces/libpq/fe-protocol3.c	2005-07-03 20:36:44.000000000 +0200
***************
*** 144,149 ****
--- 144,150 ----
  		 */
  		if (id == 'A')
  		{
+ 		
  			if (getNotify(conn))
  				return;
  		}
***************
*** 167,172 ****
--- 168,174 ----
  			 * why it is about to close the connection, so we don't want
  			 * to just discard it...)
  			 */
+ 		
  			if (id == 'E')
  			{
  				if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
***************
*** 193,198 ****
--- 195,221 ----
  			 */
  			switch (id)
  			{
+ 				case 't':
+ 					{
+ 					    char *cmd;
+ 					    char *varname;
+ 					    char *expr;
+ 					
+ 					    if (conn->traceProc != NULL)
+             					(*conn->traceProc) (&cmd, &varname, &expr);
+ 
+ 					    pqPutMsgStart('T', false, conn);
+ 					    pqPutc((cmd)?cmd[0]:'q', conn);
+ 					    pqPuts((varname)?varname:"", conn);
+ 					    pqPuts((expr)?expr:"", conn);
+ 					    pqPutMsgEnd(conn);
+ 					    pqFlush(conn);
+ 					    
+ 					    if (cmd) free(cmd);
+ 					    if (varname) free(varname);
+ 					    if (expr) free(expr);
+ 					}
+ 					break;
  				case 'C':		/* command complete */
  					if (pqGets(&conn->workBuffer, conn))
  						return;
diff -c -r pgsql.00/src/interfaces/libpq/libpq-fe.h psql.01/src/interfaces/libpq/libpq-fe.h
*** pgsql.00/src/interfaces/libpq/libpq-fe.h	2005-06-13 04:26:00.000000000 +0200
--- psql.01/src/interfaces/libpq/libpq-fe.h	2005-07-03 19:40:41.000000000 +0200
***************
*** 140,145 ****
--- 140,146 ----
  /* Function types for notice-handling callbacks */
  typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
  typedef void (*PQnoticeProcessor) (void *arg, const char *message);
+ typedef void (*PQtraceProcessor) (char **cmd, char **varname, char **expr);
  
  /* Print options for PQprint() */
  typedef char pqbool;
***************
*** 296,301 ****
--- 297,304 ----
  extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
  					 PQnoticeProcessor proc,
  					 void *arg);
+ extern PQtraceProcessor PQsetTraceProcessor(PGconn *conn,
+ 					PQtraceProcessor proc);
  
  /*
   *	   Used to set callback that prevents concurrent access to
diff -c -r pgsql.00/src/interfaces/libpq/libpq-int.h psql.01/src/interfaces/libpq/libpq-int.h
*** pgsql.00/src/interfaces/libpq/libpq-int.h	2005-06-27 04:04:00.000000000 +0200
--- psql.01/src/interfaces/libpq/libpq-int.h	2005-07-03 19:37:42.000000000 +0200
***************
*** 333,338 ****
--- 333,339 ----
  	/* Status for asynchronous result construction */
  	PGresult   *result;			/* result being constructed */
  	PGresAttValue *curTuple;	/* tuple currently being read */
+ 	PQtraceProcessor traceProc;
  
  #ifdef USE_SSL
  	bool		allow_ssl_try;	/* Allowed to try SSL negotiation */
diff -c -r pgsql.00/src/pl/plpgsql/src/gram.y psql.01/src/pl/plpgsql/src/gram.y
*** pgsql.00/src/pl/plpgsql/src/gram.y	2005-06-22 03:35:00.000000000 +0200
--- psql.01/src/pl/plpgsql/src/gram.y	2005-07-03 15:34:05.000000000 +0200
***************
*** 56,61 ****
--- 56,62 ----
  											   PLpgSQL_datum *initial_datum);
  static	void			 check_sql_expr(const char *stmt);
  static	void			 plpgsql_sql_error_callback(void *arg);
+ char * plpgsql_scanner_src(void);
  
  %}
  
***************
*** 145,150 ****
--- 146,152 ----
  %type <ival>	getdiag_kind getdiag_target
  
  %type <ival>	lno
+ %type <str>	src;
  
  		/*
  		 * Keyword tokens
***************
*** 222,228 ****
  
  pl_function		: T_FUNCTION comp_optsect pl_block opt_semi
  					{
! 						yylval.program = (PLpgSQL_stmt_block *)$3;
  					}
  				| T_TRIGGER comp_optsect pl_block opt_semi
  					{
--- 224,231 ----
  
  pl_function		: T_FUNCTION comp_optsect pl_block opt_semi
  					{
! 					    	yylval.program = (PLpgSQL_stmt_block *)$3;
! 					
  					}
  				| T_TRIGGER comp_optsect pl_block opt_semi
  					{
***************
*** 261,266 ****
--- 264,270 ----
  						new->initvarnos = $1.initvarnos;
  						new->body		= $4;
  						new->exceptions	= $5;
+ 						new->src = NULL;
  
  						plpgsql_ns_pop();
  
***************
*** 623,628 ****
--- 627,633 ----
  						new = palloc0(sizeof(PLpgSQL_stmt_perform));
  						new->cmd_type = PLPGSQL_STMT_PERFORM;
  						new->lineno   = $2;
+ 						new->breakpoint = false;
  						new->expr  = $3;
  
  						$$ = (PLpgSQL_stmt *)new;
***************
*** 636,641 ****
--- 641,647 ----
  						new = palloc0(sizeof(PLpgSQL_stmt_assign));
  						new->cmd_type = PLPGSQL_STMT_ASSIGN;
  						new->lineno   = $2;
+ 						new->breakpoint = false;
  						new->varno = $1;
  						new->expr  = $4;
  
***************
*** 649,654 ****
--- 655,661 ----
  
  						new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
  						new->cmd_type = PLPGSQL_STMT_GETDIAG;
+ 						new->breakpoint = false;
  						new->lineno   = $3;
  						new->diag_items  = $4;
  
***************
*** 736,741 ****
--- 743,749 ----
  						new->cond		= $3;
  						new->true_body	= $4;
  						new->false_body = $5;
+ 						new->breakpoint = false;
  
  						$$ = (PLpgSQL_stmt *)new;
  					}
***************
*** 768,773 ****
--- 776,782 ----
  						new_if->lineno		= $2;
  						new_if->cond		= $3;
  						new_if->true_body	= $4;
+ 						new_if->breakpoint = false;
  						new_if->false_body	= $5;
  
  						/* wrap the if-statement in a "container" list */
***************
*** 789,794 ****
--- 798,804 ----
  						new->lineno   = $3;
  						new->label	  = $1;
  						new->body	  = $4;
+ 						new->breakpoint = false;
  
  						plpgsql_ns_pop();
  
***************
*** 806,811 ****
--- 816,822 ----
  						new->label	  = $1;
  						new->cond	  = $4;
  						new->body	  = $5;
+ 						new->breakpoint = false;
  
  						plpgsql_ns_pop();
  
***************
*** 866,871 ****
--- 877,883 ----
  							new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
  							new->cmd_type = PLPGSQL_STMT_DYNFORS;
  							new->lineno   = $1;
+ 							new->breakpoint = false;
  							if ($2.rec)
  								new->rec = $2.rec;
  							else if ($2.row)
***************
*** 945,950 ****
--- 957,963 ----
  								new->reverse  = reverse;
  								new->lower	  = expr1;
  								new->upper	  = expr2;
+ 								new->breakpoint = false;
  
  								$$ = (PLpgSQL_stmt *) new;
  							}
***************
*** 970,975 ****
--- 983,989 ----
  
  								new = palloc0(sizeof(PLpgSQL_stmt_fors));
  								new->cmd_type = PLPGSQL_STMT_FORS;
+ 								new->breakpoint = false;
  								new->lineno   = $1;
  								if ($2.rec)
  									new->rec = $2.rec;
***************
*** 1047,1052 ****
--- 1061,1067 ----
  						new->lineno	  = $2;
  						new->label	  = $3;
  						new->cond	  = $4;
+ 						new->breakpoint = false;
  
  						$$ = (PLpgSQL_stmt *)new;
  					}
***************
*** 1071,1076 ****
--- 1086,1092 ----
  						new->lineno   = $2;
  						new->expr	  = NULL;
  						new->retvarno = -1;
+ 						new->breakpoint = false;
  
  						if (plpgsql_curr_compile->fn_retset)
  						{
***************
*** 1137,1142 ****
--- 1153,1159 ----
  						new->lineno		= $2;
  						new->expr = NULL;
  						new->retvarno	= -1;
+ 						new->breakpoint = false;
  
  						if (plpgsql_curr_compile->out_param_varno >= 0)
  						{
***************
*** 1182,1187 ****
--- 1199,1205 ----
  						new->elog_level = $3;
  						new->message	= $4;
  						new->params		= NIL;
+ 						new->breakpoint = false;
  
  						tok = yylex();
  
***************
*** 1274,1279 ****
--- 1292,1298 ----
  						new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
  						new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
  						new->lineno   = $2;
+ 						new->breakpoint = false;
  						new->query    = expr;
  						new->rec = NULL;
  						new->row = NULL;
***************
*** 1324,1329 ****
--- 1343,1349 ----
  
  						new = palloc0(sizeof(PLpgSQL_stmt_open));
  						new->cmd_type = PLPGSQL_STMT_OPEN;
+ 						new->breakpoint = false;
  						new->lineno = $2;
  						new->curvar = $3->varno;
  
***************
*** 1440,1448 ****
--- 1460,1470 ----
  
  						new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
  						new->curvar = $3;
+ 						new->breakpoint = false;
  
  						$$ = (PLpgSQL_stmt *)new;
  						$$->lineno = $2;
+ 						
  					}
  				;
  
***************
*** 1454,1459 ****
--- 1476,1482 ----
  						new->cmd_type = PLPGSQL_STMT_CLOSE;
  						new->lineno = $2;
  						new->curvar = $3;
+ 						new->breakpoint = false;
  
  						$$ = (PLpgSQL_stmt *)new;
  					}
***************
*** 1463,1468 ****
--- 1486,1492 ----
  					{
  						/* We do not bother building a node for NULL */
  						$$ = NULL;
+ 						
  					}
  				;
  
***************
*** 1645,1650 ****
--- 1669,1679 ----
  					}
  				;
  
+ src				:
+ 					{
+ 						$$ = plpgsql_scanner_src();
+ 					}
+ 				;
  %%
  
  
diff -c -r pgsql.00/src/pl/plpgsql/src/pl_comp.c psql.01/src/pl/plpgsql/src/pl_comp.c
*** pgsql.00/src/pl/plpgsql/src/pl_comp.c	2005-06-10 18:23:00.000000000 +0200
--- psql.01/src/pl/plpgsql/src/pl_comp.c	2005-07-03 15:33:39.000000000 +0200
***************
*** 641,647 ****
  	if (parse_rc != 0)
  		elog(ERROR, "plpgsql parser returned %d", parse_rc);
  	function->action = plpgsql_yylval.program;
! 
  	plpgsql_scanner_finish();
  	pfree(proc_source);
  
--- 641,647 ----
  	if (parse_rc != 0)
  		elog(ERROR, "plpgsql parser returned %d", parse_rc);
  	function->action = plpgsql_yylval.program;
! 	function->src = pstrdup(proc_source);
  	plpgsql_scanner_finish();
  	pfree(proc_source);
  
diff -c -r pgsql.00/src/pl/plpgsql/src/pl_exec.c psql.01/src/pl/plpgsql/src/pl_exec.c
*** pgsql.00/src/pl/plpgsql/src/pl_exec.c	2005-06-27 00:05:00.000000000 +0200
--- psql.01/src/pl/plpgsql/src/pl_exec.c	2005-07-03 20:19:39.000000000 +0200
***************
*** 53,63 ****
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/typcache.h"
! 
  
  static const char *const raise_skip_msg = "RAISE";
  
  
  /*
   * All plpgsql function executions within a single transaction share
   * the same executor EState for evaluating "simple" expressions.  Each
--- 53,67 ----
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/typcache.h"
! #include "libpq/libpq.h"
! #include "libpq/pqformat.h"
! #include "utils/guc.h"
  
  static const char *const raise_skip_msg = "RAISE";
  
  
+ 
+ 
  /*
   * All plpgsql function executions within a single transaction share
   * the same executor EState for evaluating "simple" expressions.  Each
***************
*** 70,75 ****
--- 74,80 ----
   */
  static EState *simple_eval_estate = NULL;
  static PLpgSQL_expr *active_simple_exprs = NULL;
+ static bool gdb_continue = false;
  
  /************************************************************
   * Local function forward declarations
***************
*** 181,187 ****
  static bool compatible_tupdesc(TupleDesc td1, TupleDesc td2);
  static void exec_set_found(PLpgSQL_execstate *estate, bool state);
  static void free_var(PLpgSQL_var *var);
! 
  
  /* ----------
   * plpgsql_exec_function	Called by the call handler for
--- 186,194 ----
  static bool compatible_tupdesc(TupleDesc td1, TupleDesc td2);
  static void exec_set_found(PLpgSQL_execstate *estate, bool state);
  static void free_var(PLpgSQL_var *var);
! static char* exec_getline(int lno, char *src);
! static void exec_sendinfo(const char *fmt, ...);
! static char *pstrndup(char *src, int size);
  
  /* ----------
   * plpgsql_exec_function	Called by the call handler for
***************
*** 200,206 ****
--- 207,216 ----
  	 * Setup the execution state
  	 */
  	plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo);
+ 	estate.src = func->src;
  
+ exec_sendinfo("executing function %s", func->fn_name);
+ gdb_continue = false;
  	/*
  	 * Setup error traceback support for ereport()
  	 */
***************
*** 284,289 ****
--- 294,302 ----
  	estate.err_text = NULL;
  	estate.err_stmt = (PLpgSQL_stmt *) (func->action);
  	rc = exec_stmt_block(&estate, func->action);
+ 	
+ 	//estate.src = func->action->src;
+ 	
  	if (rc != PLPGSQL_RC_RETURN)
  	{
  		estate.err_stmt = NULL;
***************
*** 553,558 ****
--- 566,573 ----
  	 * Set the magic variable FOUND to false
  	 */
  	exec_set_found(&estate, false);
+ 	
+ 	estate.src = func->action->src;
  
  	/*
  	 * Now call the toplevel block of statements
***************
*** 992,1008 ****
   *				type specific execution function.
   * ----------
   */
  static int
  exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
  {
  	PLpgSQL_stmt *save_estmt;
  	int			rc = -1;
  
  	save_estmt = estate->err_stmt;
  	estate->err_stmt = stmt;
! 
  	CHECK_FOR_INTERRUPTS();
  
  	switch (stmt->cmd_type)
  	{
  		case PLPGSQL_STMT_BLOCK:
--- 1007,1231 ----
   *				type specific execution function.
   * ----------
   */
+  
+ 
+ static void
+ exec_sendinfo(const char *fmt, ...)
+ {
+         StringInfoData msgbuf, dtabuf;
+ 
+ 	initStringInfo(&dtabuf);
+ 	dtabuf.maxlen = 30000;
+ 
+ 	for (;;)
+ 	{
+ 	    va_list args;
+ 	    bool success;
+ 	    
+ 	    va_start(args, fmt); 
+ 	    success = appendStringInfoVA(&dtabuf, fmt, args); 
+             va_end(args); 
+             if (success) 
+ 		break;
+ 	    enlargeStringInfo(&dtabuf, dtabuf.maxlen); 
+         } 
+ 	
+         pq_beginmessage(&msgbuf, 'N');
+ 
+         pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
+         pq_sendstring(&msgbuf, "trace");
+ 	
+         pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY);
+         pq_sendstring(&msgbuf, dtabuf.data);
+ 	
+ 	pq_sendbyte(&msgbuf, '\0'); 
+ 	pq_endmessage(&msgbuf);
+ 	
+ 	pq_flush();
+ 	
+ 	pfree(dtabuf.data);
+ }
+ 
+ static char *
+ exec_getline(int ln, char *src)
+ {
+     int cl = 1; 
+     char *c;
+     
+     if (*src == '\n')
+ 	src++;
+     
+     while (src)
+     {
+ 	if ((c = strchr(src,'\n')) == NULL)
+ 	{
+ 	    if (cl != ln)
+ 		return NULL;
+ 	    return pstrdup(src);
+ 	}    
+ 	if (cl++ == ln)
+ 	    return pstrndup(src, c - src);
+ 	src = c + 1;
+     }
+     return NULL;
+ }    
+  
+ static char *
+ pstrndup(char *str, int size)
+ {
+     char *res = palloc(size + 1);
+     memcpy(res, str, size);
+     res[size] = '\0';
+     return res;
+ }
+ 
  static int
  exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
  {
  	PLpgSQL_stmt *save_estmt;
  	int			rc = -1;
+ 	bool	first_time = true;
  
  	save_estmt = estate->err_stmt;
  	estate->err_stmt = stmt;
! 	
  	CHECK_FOR_INTERRUPTS();
  
+ 	if (trace_plpgsql)
+ 		for (;;)
+ 		{
+ 			char cmd;
+ 			char *varname;
+ 			char *expr;
+ 			char mtype;
+ 			StringInfoData buf;
+ 
+     
+ 			if (first_time)
+ 			{
+ 				char *line = exec_getline(stmt->lineno, estate->src);
+ 				exec_sendinfo("%s on %d: %s", plpgsql_stmt_typename(stmt), stmt->lineno,line);
+ 				if (line) pfree(line);
+ 				first_time = false;
+ 			}
+ 		
+ 			/* noninterctive debug */
+ 			if (gdb_continue && !stmt->breakpoint)
+ 				break;
+ 			if (gdb_continue)
+ 			    exec_sendinfo("stop on breakpoint");
+ 			    
+ 			gdb_continue = false;
+ 		
+ 			pq_putemptymessage('t');
+ 			pq_flush();
+     
+ 			mtype = pq_getbyte();
+ 			if (mtype == EOF)
+         			ereport(ERROR,
+             				(errcode(ERRCODE_CONNECTION_FAILURE),
+                 			errmsg("unexpected EOF on client connection")));
+ 
+ 			initStringInfo(&buf);    
+ 			if (pq_getmessage(&buf, 1000))
+ 			{
+     				pfree(buf.data);
+         			ereport(ERROR,
+             				(errcode(ERRCODE_CONNECTION_FAILURE),
+                 			errmsg("unexpected EOF on client connection")));
+ 			}  
+ 			if (mtype != 'T')
+ 			{
+ 				pfree(buf.data);
+         			ereport(ERROR,
+             				(errcode(ERRCODE_PROTOCOL_VIOLATION),
+                     			errmsg("unexpected message type 0x%02X during TRACE op ", mtype)));
+ 			}
+ 			cmd = pq_getmsgbyte(&buf);
+ 			varname = (char *) pq_getmsgstring(&buf);
+ 			expr = (char *) pq_getmsgstring(&buf);
+ 			pq_getmsgend(&buf);
+     
+ 			CHECK_FOR_INTERRUPTS();
+     
+ 			if (cmd == 's' || cmd == 'c')
+ 			{
+ 				pfree(buf.data);
+ 				gdb_continue = (cmd == 'c');
+ 				break;
+ 			}
+ 
+ 			switch (cmd)
+ 			{
+ 				case 'q':
+ 					pfree(buf.data);
+ 					elog(ERROR, "end of tracing");
+ 					break;
+ 				case 'l':
+ 				    {
+ 					StringInfoData list;
+ 					int lno = 1; 
+ 					char *c; 
+ 					char *src = estate->src;
+ 			
+ 					initStringInfo(&list);
+ 					appendStringInfo(&list, "source of function %s\n", estate->err_func->fn_name);
+ 			
+ 					if (*src == '\n') 
+ 						src++;
+ 					while (src)
+ 					{
+ 						if ((c = strchr(src,'\n')) == NULL)
+ 						{
+ 							appendStringInfo(&list, "%3d: %s\n", lno, src);
+ 							break;
+ 						}
+ 						else
+ 						{
+ 							char *s;
+ 							s = pstrndup(src, c - src);
+ 							appendStringInfo(&list, "%3d: %s\n", lno++, s);
+ 							pfree(s);
+ 							src = c+1;
+ 						}
+ 					}
+ 					exec_sendinfo(list.data);
+ 					pfree(list.data);
+ 				    }
+ 				    break;
+ 				case 'p':
+ 				    {
+ 					char *extval;
+ 					int i;
+ 					for (i = estate->ndatums-1;i>=0;i--)
+ 	    				{
+ 						PLpgSQL_var *var = (PLpgSQL_var *) estate->datums[i];
+ 						if (strcmp(varname,"*") == 0|| strcmp(varname, var->refname) == 0)
+ 						{
+ 							extval = (var->isnull)?"<NULL>":
+ 								convert_value_to_string(var->value, var->datatype->typoid);    
+ 				    
+ 							exec_sendinfo("var %s as %s has %s", var->refname, var->datatype->typname, extval);
+ 						}
+ 					} 		    
+ 				    }
+ 				    break;
+ 				case 'b':
+ 					if (stmt->breakpoint)
+ 					{
+ 						stmt->breakpoint = false;
+ 						exec_sendinfo("Breakpoint set off");
+ 					} else
+ 					{
+ 						stmt->breakpoint = true;
+ 						exec_sendinfo("Breakpoint set on");    
+ 					}
+ 					break;
+ 				default:
+ 					exec_sendinfo("Unknown dbg command");
+ 			}
+ 		}	
+ 
  	switch (stmt->cmd_type)
  	{
  		case PLPGSQL_STMT_BLOCK:
***************
*** 2114,2119 ****
--- 2337,2344 ----
  	estate->err_func = func;
  	estate->err_stmt = NULL;
  	estate->err_text = NULL;
+ 	
+ 	estate->src = NULL;
  
  	/*
  	 * Create an EState for evaluation of simple expressions, if there's
diff -c -r pgsql.00/src/pl/plpgsql/src/plpgsql.h psql.01/src/pl/plpgsql/src/plpgsql.h
*** pgsql.00/src/pl/plpgsql/src/plpgsql.h	2005-06-22 03:35:00.000000000 +0200
--- psql.01/src/pl/plpgsql/src/plpgsql.h	2005-07-03 13:51:59.000000000 +0200
***************
*** 313,318 ****
--- 313,319 ----
  {								/* Generic execution node		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool		breakpoint;
  } PLpgSQL_stmt;
  
  
***************
*** 342,347 ****
--- 343,350 ----
  {								/* Block of statements			*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
+ 	char	   *src;
  	char	   *label;
  	List	   *body;			/* List of statements */
  	int			n_initvars;
***************
*** 354,359 ****
--- 357,363 ----
  {								/* Assign statement			*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	int			varno;
  	PLpgSQL_expr *expr;
  } PLpgSQL_stmt_assign;
***************
*** 362,367 ****
--- 366,372 ----
  {								/* PERFORM statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_expr *expr;
  } PLpgSQL_stmt_perform;
  
***************
*** 375,380 ****
--- 380,386 ----
  {								/* Get Diagnostics statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	List	   *diag_items;		/* List of PLpgSQL_diag_item */
  } PLpgSQL_stmt_getdiag;
  
***************
*** 383,388 ****
--- 389,395 ----
  {								/* IF statement				*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_expr *cond;
  	List	   *true_body;		/* List of statements */
  	List	   *false_body;		/* List of statements */
***************
*** 393,398 ****
--- 400,406 ----
  {								/* Unconditional LOOP statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	char	   *label;
  	List	   *body;			/* List of statements */
  } PLpgSQL_stmt_loop;
***************
*** 402,407 ****
--- 410,416 ----
  {								/* WHILE cond LOOP statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	char	   *label;
  	PLpgSQL_expr *cond;
  	List	   *body;			/* List of statements */
***************
*** 412,417 ****
--- 421,427 ----
  {								/* FOR statement with integer loopvar	*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	char	   *label;
  	PLpgSQL_var *var;
  	PLpgSQL_expr *lower;
***************
*** 425,430 ****
--- 435,441 ----
  {								/* FOR statement running over SELECT	*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	char	   *label;
  	PLpgSQL_rec *rec;
  	PLpgSQL_row *row;
***************
*** 437,442 ****
--- 448,454 ----
  {								/* FOR statement running over EXECUTE	*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	char	   *label;
  	PLpgSQL_rec *rec;
  	PLpgSQL_row *row;
***************
*** 449,454 ****
--- 461,467 ----
  {								/* SELECT ... INTO statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_rec *rec;
  	PLpgSQL_row *row;
  	PLpgSQL_expr *query;
***************
*** 459,464 ****
--- 472,478 ----
  {								/* OPEN a curvar					*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	int			curvar;
  	PLpgSQL_row *returntype;
  	PLpgSQL_expr *argquery;
***************
*** 471,476 ****
--- 485,491 ----
  {								/* FETCH curvar INTO statement		*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_rec *rec;
  	PLpgSQL_row *row;
  	int			curvar;
***************
*** 481,486 ****
--- 496,502 ----
  {								/* CLOSE curvar						*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	int			curvar;
  } PLpgSQL_stmt_close;
  
***************
*** 489,494 ****
--- 505,511 ----
  {								/* EXIT or CONTINUE statement			*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	bool		is_exit;		/* Is this an exit or a continue? */
  	char	   *label;
  	PLpgSQL_expr *cond;
***************
*** 499,504 ****
--- 516,522 ----
  {								/* RETURN statement			*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_expr *expr;
  	int			retvarno;
  } PLpgSQL_stmt_return;
***************
*** 507,512 ****
--- 525,531 ----
  {								/* RETURN NEXT statement */
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_expr *expr;
  	int			retvarno;
  } PLpgSQL_stmt_return_next;
***************
*** 515,520 ****
--- 534,540 ----
  {								/* RAISE statement			*/
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	int			elog_level;
  	char	   *message;
  	List	   *params;			/* list of expressions */
***************
*** 525,530 ****
--- 545,551 ----
  {								/* Generic SQL statement to execute */
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_expr *sqlstmt;
  } PLpgSQL_stmt_execsql;
  
***************
*** 533,538 ****
--- 554,560 ----
  {								/* Dynamic SQL string to execute */
  	int			cmd_type;
  	int			lineno;
+ 	bool	breakpoint;
  	PLpgSQL_rec *rec;					/* INTO record or row variable */
  	PLpgSQL_row *row;
  	PLpgSQL_expr *query;
***************
*** 594,599 ****
--- 616,622 ----
  	int			tg_nargs_varno;
  
  	int			ndatums;
+ 	char		*src;
  	PLpgSQL_datum **datums;
  	PLpgSQL_stmt_block *action;
  } PLpgSQL_function;
***************
*** 608,613 ****
--- 631,637 ----
  	Oid			fn_rettype;		/* info about declared function rettype */
  	bool		retistuple;
  	bool		retisset;
+ 	char		*src;
  
  	bool		readonly_func;
  
Pouze v psql.01/src/pl/plpgsql/src: pl_scan.c
diff -c -r pgsql.00/src/pl/plpgsql/src/scan.l psql.01/src/pl/plpgsql/src/scan.l
*** pgsql.00/src/pl/plpgsql/src/scan.l	2005-06-26 21:16:00.000000000 +0200
--- psql.01/src/pl/plpgsql/src/scan.l	2005-07-03 10:39:27.000000000 +0200
***************
*** 478,483 ****
--- 478,490 ----
  	return cur_line_num;
  }
  
+ 
+ char *
+ plpgsql_scanner_src(void)
+ {
+     return cur_line_start;
+ }
+ 
  /*
   * Called before any actual parsing is done
   *
