%}
 
+%parse-param {PLpgSQL_stmt_block **plpgsql_parse_result_p}
 %parse-param {yyscan_t yyscanner}
 %lex-param   {yyscan_t yyscanner}
 %pure-parser
 
 pl_function        : comp_options pl_block opt_semi
                    {
-                       plpgsql_parse_result = (PLpgSQL_stmt_block *) $2;
+                       *plpgsql_parse_result_p = (PLpgSQL_stmt_block *) $2;
                        (void) yynerrs;     /* suppress compiler warning */
                    }
                ;
                        if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
                                              $1.ident, NULL, NULL,
                                              NULL) != NULL)
-                           yyerror(&yylloc, yyscanner, "duplicate declaration");
+                           yyerror(&yylloc, NULL, yyscanner, "duplicate declaration");
 
                        if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR ||
                            plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR)
                        if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
                                              $1, NULL, NULL,
                                              NULL) != NULL)
-                           yyerror(&yylloc, yyscanner, "duplicate declaration");
+                           yyerror(&yylloc, NULL, yyscanner, "duplicate declaration");
 
                        if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR ||
                            plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR)
                                                K_RETURNED_SQLSTATE, "returned_sqlstate"))
                            $$ = PLPGSQL_GETDIAG_RETURNED_SQLSTATE;
                        else
-                           yyerror(&yylloc, yyscanner, "unrecognized GET DIAGNOSTICS item");
+                           yyerror(&yylloc, NULL, yyscanner, "unrecognized GET DIAGNOSTICS item");
                    }
                ;
 
 
                        tok = yylex(&yylval, &yylloc, yyscanner);
                        if (tok == 0)
-                           yyerror(&yylloc, yyscanner, "unexpected end of function definition");
+                           yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition");
 
                        if (tok_is_keyword(tok, &yylval,
                                           K_NEXT, "next"))
 
                        tok = yylex(&yylval, &yylloc, yyscanner);
                        if (tok == 0)
-                           yyerror(&yylloc, yyscanner, "unexpected end of function definition");
+                           yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition");
 
                        /*
                         * We could have just RAISE, meaning to re-throw
                                tok = yylex(&yylval, &yylloc, yyscanner);
                            }
                            if (tok == 0)
-                               yyerror(&yylloc, yyscanner, "unexpected end of function definition");
+                               yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition");
 
                            /*
                             * Next we can have a condition name, or
                                 */
                                tok = yylex(&yylval, &yylloc, yyscanner);
                                if (tok != ',' && tok != ';' && tok != K_USING)
-                                   yyerror(&yylloc, yyscanner, "syntax error");
+                                   yyerror(&yylloc, NULL, yyscanner, "syntax error");
 
                                while (tok == ',')
                                {
                                    char       *sqlstatestr;
 
                                    if (yylex(&yylval, &yylloc, yyscanner) != SCONST)
-                                       yyerror(&yylloc, yyscanner, "syntax error");
+                                       yyerror(&yylloc, NULL, yyscanner, "syntax error");
                                    sqlstatestr = yylval.str;
 
                                    if (strlen(sqlstatestr) != 5)
-                                       yyerror(&yylloc, yyscanner, "invalid SQLSTATE code");
+                                       yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
                                    if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
-                                       yyerror(&yylloc, yyscanner, "invalid SQLSTATE code");
+                                       yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
                                    new->condname = sqlstatestr;
                                }
                                else
                                    else if (plpgsql_token_is_unreserved_keyword(tok))
                                        new->condname = pstrdup(yylval.keyword);
                                    else
-                                       yyerror(&yylloc, yyscanner, "syntax error");
+                                       yyerror(&yylloc, NULL, yyscanner, "syntax error");
                                    plpgsql_recognize_err_condition(new->condname,
                                                                    false);
                                }
                                tok = yylex(&yylval, &yylloc, yyscanner);
                                if (tok != ';' && tok != K_USING)
-                                   yyerror(&yylloc, yyscanner, "syntax error");
+                                   yyerror(&yylloc, NULL, yyscanner, "syntax error");
                            }
 
                            if (tok == K_USING)
                            if (endtoken == K_INTO)
                            {
                                if (new->into)          /* multiple INTO */
-                                   yyerror(&yylloc, yyscanner, "syntax error");
+                                   yyerror(&yylloc, NULL, yyscanner, "syntax error");
                                new->into = true;
                                read_into_target(&new->target, &new->strict, &yylval, &yylloc, yyscanner);
                                endtoken = yylex(&yylval, &yylloc, yyscanner);
                            else if (endtoken == K_USING)
                            {
                                if (new->params)        /* multiple USING */
-                                   yyerror(&yylloc, yyscanner, "syntax error");
+                                   yyerror(&yylloc, NULL, yyscanner, "syntax error");
                                do
                                {
                                    expr = read_sql_construct(',', ';', K_INTO,
                            else if (endtoken == ';')
                                break;
                            else
-                               yyerror(&yylloc, yyscanner, "syntax error");
+                               yyerror(&yylloc, NULL, yyscanner, "syntax error");
                        }
 
                        $$ = (PLpgSQL_stmt *) new;
                            }
 
                            if (tok != K_FOR)
-                               yyerror(&yylloc, yyscanner, "syntax error, expected \"FOR\"");
+                               yyerror(&yylloc, NULL, yyscanner, "syntax error, expected \"FOR\"");
 
                            tok = yylex(&yylval, &yylloc, yyscanner);
                            if (tok == K_EXECUTE)
                        read_into_target(&target, NULL, &yylval, &yylloc, yyscanner);
 
                        if (yylex(&yylval, &yylloc, yyscanner) != ';')
-                           yyerror(&yylloc, yyscanner, "syntax error");
+                           yyerror(&yylloc, NULL, yyscanner, "syntax error");
 
                        /*
                         * We don't allow multiple rows in PL/pgSQL's FETCH
 
                                /* next token should be a string literal */
                                if (yylex(&yylval, &yylloc, yyscanner) != SCONST)
-                                   yyerror(&yylloc, yyscanner, "syntax error");
+                                   yyerror(&yylloc, NULL, yyscanner, "syntax error");
                                sqlstatestr = yylval.str;
 
                                if (strlen(sqlstatestr) != 5)
-                                   yyerror(&yylloc, yyscanner, "invalid SQLSTATE code");
+                                   yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
                                if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
-                                   yyerror(&yylloc, yyscanner, "invalid SQLSTATE code");
+                                   yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code");
 
                                new = palloc(sizeof(PLpgSQL_condition));
                                new->sqlerrstate =
                | T_DATUM
                    {
                        if ($1.ident == NULL) /* composite name not OK */
-                           yyerror(&yylloc, yyscanner, "syntax error");
+                           yyerror(&yylloc, NULL, yyscanner, "syntax error");
                        $$ = $1.ident;
                    }
                ;
    else if (tok == T_CWORD)
        cword_is_not_variable(&(yylvalp->cword), *yyllocp, yyscanner);
    else
-       yyerror(yyllocp, yyscanner, "syntax error");
+       yyerror(yyllocp, NULL, yyscanner, "syntax error");
 }
 
 /* Convenience routine to read an expression with one possible terminator */
        {
            parenlevel--;
            if (parenlevel < 0)
-               yyerror(yyllocp, yyscanner, "mismatched parentheses");
+               yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses");
        }
 
        /*
        if (tok == 0 || tok == ';')
        {
            if (parenlevel != 0)
-               yyerror(yyllocp, yyscanner, "mismatched parentheses");
+               yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses");
            if (isexpression)
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
    if (startlocation >= endlocation)
    {
        if (isexpression)
-           yyerror(yyllocp, yyscanner, "missing expression");
+           yyerror(yyllocp, NULL, yyscanner, "missing expression");
        else
-           yyerror(yyllocp, yyscanner, "missing SQL statement");
+           yyerror(yyllocp, NULL, yyscanner, "missing SQL statement");
    }
 
    /*
            if (tok == ICONST)
                tok = yylex(yylvalp, yyllocp, yyscanner);
            if (tok != ']')
-               yyerror(yyllocp, yyscanner, "syntax error, expected \"]\"");
+               yyerror(yyllocp, NULL, yyscanner, "syntax error, expected \"]\"");
            tok = yylex(yylvalp, yyllocp, yyscanner);
        }
        plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner);
        if (tok == 0)
        {
            if (parenlevel != 0)
-               yyerror(yyllocp, yyscanner, "mismatched parentheses");
+               yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses");
            else
-               yyerror(yyllocp, yyscanner, "incomplete data type declaration");
+               yyerror(yyllocp, NULL, yyscanner, "incomplete data type declaration");
        }
        /* Possible followers for datatype in a declaration */
        if (tok == K_COLLATE || tok == K_NOT ||
    type_name = ds.data;
 
    if (type_name[0] == '\0')
-       yyerror(yyllocp, yyscanner, "missing data type declaration");
+       yyerror(yyllocp, NULL, yyscanner, "missing data type declaration");
 
    result = parse_datatype(type_name, startlocation, yyscanner);
 
        if (tok == ';' && paren_depth == 0 && begin_depth == 0)
            break;
        if (tok == 0)
-           yyerror(yyllocp, yyscanner, "unexpected end of function definition");
+           yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
        if (tok == K_INTO)
        {
            if (prev_tok == K_INSERT)
            if (firsttoken == K_IMPORT)
                continue;       /* IMPORT ... INTO is not an INTO-target */
            if (have_into)
-               yyerror(yyllocp, yyscanner, "INTO specified more than once");
+               yyerror(yyllocp, NULL, yyscanner, "INTO specified more than once");
            have_into = true;
            into_start_loc = *yyllocp;
            plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
 
    tok = yylex(yylvalp, yyllocp, yyscanner);
    if (tok == 0)
-       yyerror(yyllocp, yyscanner, "unexpected end of function definition");
+       yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
 
    if (tok_is_keyword(tok, yylvalp,
                       K_NEXT, "next"))
    {
        tok = yylex(yylvalp, yyllocp, yyscanner);
        if (tok != K_FROM && tok != K_IN)
-           yyerror(yyllocp, yyscanner, "expected FROM or IN");
+           yyerror(yyllocp, NULL, yyscanner, "expected FROM or IN");
    }
 
    return fetch;
 
    tok = yylex(yylvalp, yyllocp, yyscanner);
    if (tok == 0)
-       yyerror(yyllocp, yyscanner, "unexpected end of function definition");
+       yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
 
    if (tok == K_FROM || tok == K_IN)
    {
                     parser_errposition(*yyllocp)));
 
        if (tok != until)
-           yyerror(yyllocp, yyscanner, "syntax error");
+           yyerror(yyllocp, NULL, yyscanner, "syntax error");
 
        return NULL;
    }
             */
            tok2 = yylex(yylvalp, yyllocp, yyscanner);
            if (tok2 != COLON_EQUALS)
-               yyerror(yyllocp, yyscanner, "syntax error");
+               yyerror(yyllocp, NULL, yyscanner, "syntax error");
 
            any_named = true;
        }
    /* Next we'd better find the until token */
    tok = yylex(yylvalp, yyllocp, yyscanner);
    if (tok != until)
-       yyerror(yyllocp, yyscanner, "syntax error");
+       yyerror(yyllocp, NULL, yyscanner, "syntax error");
 
    return expr;
 }
        int         tok;
 
        if ((tok = yylex(yylvalp, yyllocp, yyscanner)) == 0)
-           yyerror(yyllocp, yyscanner, "unexpected end of function definition");
+           yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition");
 
        opt = (PLpgSQL_raise_option *) palloc(sizeof(PLpgSQL_raise_option));
 
                                K_SCHEMA, "schema"))
            opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA;
        else
-           yyerror(yyllocp, yyscanner, "unrecognized RAISE statement option");
+           yyerror(yyllocp, NULL, yyscanner, "unrecognized RAISE statement option");
 
        tok = yylex(yylvalp, yyllocp, yyscanner);
        if (tok != '=' && tok != COLON_EQUALS)
-           yyerror(yyllocp, yyscanner, "syntax error, expected \"=\"");
+           yyerror(yyllocp, NULL, yyscanner, "syntax error, expected \"=\"");
 
        opt->expr = read_sql_expression2(',', ';', ", or ;", &tok, yylvalp, yyllocp, yyscanner);