1 /*-------------------------------------------------------------------------
3 * pl_funcs.c - Misc functions for the PL/pgSQL
6 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.66 2007/11/27 19:58:44 tgl Exp $
13 *-------------------------------------------------------------------------
21 #include "parser/scansup.h"
25 * Local variables for the namestack handling
28 static PLpgSQL_ns *ns_current = NULL;
29 static bool ns_localmode = false;
33 * plpgsql_dstring_init Dynamic string initialization
37 plpgsql_dstring_init(PLpgSQL_dstring *ds)
39 ds->value = palloc(ds->alloc = 512);
46 * plpgsql_dstring_free Dynamic string destruction
50 plpgsql_dstring_free(PLpgSQL_dstring *ds)
56 plpgsql_dstring_expand(PLpgSQL_dstring *ds, int needed)
58 /* Don't allow truncating the string */
59 Assert(needed > ds->alloc);
60 Assert(ds->used <= ds->alloc);
62 /* Might have to double more than once, if needed is large */
66 } while (needed > ds->alloc);
67 ds->value = repalloc(ds->value, ds->alloc);
71 * plpgsql_dstring_append Dynamic string extending
75 plpgsql_dstring_append(PLpgSQL_dstring *ds, const char *str)
77 int len = strlen(str);
78 int needed = ds->used + len;
80 if (needed > ds->alloc)
81 plpgsql_dstring_expand(ds, needed);
83 memcpy(&(ds->value[ds->used - 1]), str, len);
85 ds->value[ds->used - 1] = '\0';
89 * plpgsql_dstring_append_char Append a single character
94 plpgsql_dstring_append_char(PLpgSQL_dstring *ds, char c)
96 if (ds->used == ds->alloc)
97 plpgsql_dstring_expand(ds, ds->used + 1);
99 ds->value[ds->used - 1] = c;
100 ds->value[ds->used] = '\0';
106 * plpgsql_dstring_get Dynamic string get value
110 plpgsql_dstring_get(PLpgSQL_dstring *ds)
117 * plpgsql_ns_init Initialize the namestack
121 plpgsql_ns_init(void)
124 ns_localmode = false;
129 * plpgsql_ns_setlocal Tell plpgsql_ns_lookup whether to
130 * look into the current level only.
132 * This is a crock, but in the current design we need it because scan.l
133 * initiates name lookup, and the scanner does not know whether we are
134 * examining a name being declared in a DECLARE section. For that case
135 * we only want to know if there is a conflicting name earlier in the
136 * same DECLARE section. So the grammar must temporarily set local mode
137 * before scanning decl_varnames.
141 plpgsql_ns_setlocal(bool flag)
145 oldstate = ns_localmode;
152 * plpgsql_ns_push Enter a new namestack level
156 plpgsql_ns_push(const char *label)
163 new = palloc0(sizeof(PLpgSQL_ns));
164 new->upper = ns_current;
167 plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
172 * plpgsql_ns_pop Return to the previous level
182 ns_current = old->upper;
184 for (i = 0; i < old->items_used; i++)
185 pfree(old->items[i]);
192 * plpgsql_ns_additem Add an item to the current
197 plpgsql_ns_additem(int itemtype, int itemno, const char *name)
199 PLpgSQL_ns *ns = ns_current;
202 Assert(name != NULL);
204 if (ns->items_used == ns->items_alloc)
206 if (ns->items_alloc == 0)
208 ns->items_alloc = 32;
209 ns->items = palloc(sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
213 ns->items_alloc *= 2;
214 ns->items = repalloc(ns->items,
215 sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
219 nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
220 nse->itemtype = itemtype;
221 nse->itemno = itemno;
222 strcpy(nse->name, name);
223 ns->items[ns->items_used++] = nse;
228 * plpgsql_ns_lookup Lookup an identifier in the namestack
230 * Note that this only searches for variables, not labels.
232 * name1 must be non-NULL. Pass NULL for name2 and/or name3 if parsing a name
233 * with fewer than three components.
235 * If names_used isn't NULL, *names_used receives the number of names
236 * matched: 0 if no match, 1 if name1 matched an unqualified variable name,
237 * 2 if name1 and name2 matched a block label + variable name.
239 * Note that name3 is never directly matched to anything. However, if it
240 * isn't NULL, we will disregard qualified matches to scalar variables.
241 * Similarly, if name2 isn't NULL, we disregard unqualified matches to
246 plpgsql_ns_lookup(const char *name1, const char *name2, const char *name3,
252 /* Scan each level of the namestack */
253 for (ns = ns_current; ns != NULL; ns = ns->upper)
255 /* Check for unqualified match to variable name */
256 for (i = 1; i < ns->items_used; i++)
258 PLpgSQL_nsitem *nsitem = ns->items[i];
260 if (strcmp(nsitem->name, name1) == 0)
263 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
272 /* Check for qualified match to variable name */
274 strcmp(ns->items[0]->name, name1) == 0)
276 for (i = 1; i < ns->items_used; i++)
278 PLpgSQL_nsitem *nsitem = ns->items[i];
280 if (strcmp(nsitem->name, name2) == 0)
283 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
294 break; /* do not look into upper levels */
297 /* This is just to suppress possibly-uninitialized-variable warnings */
300 return NULL; /* No match found */
305 * plpgsql_ns_lookup_label Lookup a label in the namestack
309 plpgsql_ns_lookup_label(const char *name)
313 for (ns = ns_current; ns != NULL; ns = ns->upper)
315 if (strcmp(ns->items[0]->name, name) == 0)
319 return NULL; /* label not found */
324 * plpgsql_ns_rename Rename a namespace entry
328 plpgsql_ns_rename(char *oldname, char *newname)
331 PLpgSQL_nsitem *newitem;
335 * Lookup name in the namestack
337 for (ns = ns_current; ns != NULL; ns = ns->upper)
339 for (i = 1; i < ns->items_used; i++)
341 if (strcmp(ns->items[i]->name, oldname) == 0)
343 newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
344 newitem->itemtype = ns->items[i]->itemtype;
345 newitem->itemno = ns->items[i]->itemno;
346 strcpy(newitem->name, newname);
352 ns->items[i] = newitem;
359 (errcode(ERRCODE_UNDEFINED_OBJECT),
360 errmsg("there is no variable \"%s\" in the current block",
366 * plpgsql_convert_ident
368 * Convert a possibly-qualified identifier to internal form: handle
369 * double quotes, translate to lower case where not inside quotes,
370 * truncate to NAMEDATALEN.
372 * There may be several identifiers separated by dots and optional
373 * whitespace. Each one is converted to a separate palloc'd string.
374 * The caller passes the expected number of identifiers, as well as
375 * a char* array to hold them. It is an error if we find the wrong
376 * number of identifiers (cf grammar processing of fori_varname).
378 * NOTE: the input string has already been accepted by the flex lexer,
379 * so we don't need a heckuva lot of error checking here.
383 plpgsql_convert_ident(const char *s, char **output, int numidents)
385 const char *sstart = s;
388 /* Outer loop over identifiers */
394 /* Process current identifier */
398 /* Quoted identifier: copy, collapsing out doubled quotes */
400 curident = palloc(strlen(s) + 1); /* surely enough room */
413 if (*s != '"') /* should not happen if lexer checked */
415 (errcode(ERRCODE_SYNTAX_ERROR),
416 errmsg("unterminated \" in name: %s", sstart)));
419 /* Truncate to NAMEDATALEN */
420 truncate_identifier(curident, cp - curident, false);
424 /* Normal identifier: extends till dot or whitespace */
425 const char *thisstart = s;
427 while (*s && *s != '.' && !scanner_isspace(*s))
429 /* Downcase and truncate to NAMEDATALEN */
430 curident = downcase_truncate_identifier(thisstart, s - thisstart,
434 /* Pass ident to caller */
435 if (identctr < numidents)
436 output[identctr++] = curident;
439 (errcode(ERRCODE_SYNTAX_ERROR),
440 errmsg("qualified identifier cannot be used here: %s",
443 /* If not done, skip whitespace, dot, whitespace */
446 while (*s && scanner_isspace(*s))
449 elog(ERROR, "expected dot between identifiers: %s", sstart);
450 while (*s && scanner_isspace(*s))
453 elog(ERROR, "expected another identifier: %s", sstart);
457 if (identctr != numidents)
458 elog(ERROR, "improperly qualified identifier: %s",
464 * Statement type as a string, for use in error messages etc.
467 plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
469 switch (stmt->cmd_type)
471 case PLPGSQL_STMT_BLOCK:
472 return _("statement block");
473 case PLPGSQL_STMT_ASSIGN:
474 return _("assignment");
475 case PLPGSQL_STMT_IF:
477 case PLPGSQL_STMT_LOOP:
479 case PLPGSQL_STMT_WHILE:
481 case PLPGSQL_STMT_FORI:
482 return _("FOR with integer loop variable");
483 case PLPGSQL_STMT_FORS:
484 return _("FOR over SELECT rows");
485 case PLPGSQL_STMT_EXIT:
487 case PLPGSQL_STMT_RETURN:
489 case PLPGSQL_STMT_RETURN_NEXT:
490 return "RETURN NEXT";
491 case PLPGSQL_STMT_RETURN_QUERY:
492 return "RETURN QUERY";
493 case PLPGSQL_STMT_RAISE:
495 case PLPGSQL_STMT_EXECSQL:
496 return _("SQL statement");
497 case PLPGSQL_STMT_DYNEXECUTE:
498 return _("EXECUTE statement");
499 case PLPGSQL_STMT_DYNFORS:
500 return _("FOR over EXECUTE statement");
501 case PLPGSQL_STMT_GETDIAG:
502 return "GET DIAGNOSTICS";
503 case PLPGSQL_STMT_OPEN:
505 case PLPGSQL_STMT_FETCH:
507 case PLPGSQL_STMT_CLOSE:
509 case PLPGSQL_STMT_PERFORM:
517 /**********************************************************************
518 * Debug functions for analyzing the compiled code
519 **********************************************************************/
520 static int dump_indent;
522 static void dump_ind(void);
523 static void dump_stmt(PLpgSQL_stmt *stmt);
524 static void dump_block(PLpgSQL_stmt_block *block);
525 static void dump_assign(PLpgSQL_stmt_assign *stmt);
526 static void dump_if(PLpgSQL_stmt_if *stmt);
527 static void dump_loop(PLpgSQL_stmt_loop *stmt);
528 static void dump_while(PLpgSQL_stmt_while *stmt);
529 static void dump_fori(PLpgSQL_stmt_fori *stmt);
530 static void dump_fors(PLpgSQL_stmt_fors *stmt);
531 static void dump_exit(PLpgSQL_stmt_exit *stmt);
532 static void dump_return(PLpgSQL_stmt_return *stmt);
533 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
534 static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
535 static void dump_raise(PLpgSQL_stmt_raise *stmt);
536 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
537 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
538 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
539 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
540 static void dump_open(PLpgSQL_stmt_open *stmt);
541 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
542 static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt);
543 static void dump_close(PLpgSQL_stmt_close *stmt);
544 static void dump_perform(PLpgSQL_stmt_perform *stmt);
545 static void dump_expr(PLpgSQL_expr *expr);
553 for (i = 0; i < dump_indent; i++)
558 dump_stmt(PLpgSQL_stmt *stmt)
560 printf("%3d:", stmt->lineno);
561 switch (stmt->cmd_type)
563 case PLPGSQL_STMT_BLOCK:
564 dump_block((PLpgSQL_stmt_block *) stmt);
566 case PLPGSQL_STMT_ASSIGN:
567 dump_assign((PLpgSQL_stmt_assign *) stmt);
569 case PLPGSQL_STMT_IF:
570 dump_if((PLpgSQL_stmt_if *) stmt);
572 case PLPGSQL_STMT_LOOP:
573 dump_loop((PLpgSQL_stmt_loop *) stmt);
575 case PLPGSQL_STMT_WHILE:
576 dump_while((PLpgSQL_stmt_while *) stmt);
578 case PLPGSQL_STMT_FORI:
579 dump_fori((PLpgSQL_stmt_fori *) stmt);
581 case PLPGSQL_STMT_FORS:
582 dump_fors((PLpgSQL_stmt_fors *) stmt);
584 case PLPGSQL_STMT_EXIT:
585 dump_exit((PLpgSQL_stmt_exit *) stmt);
587 case PLPGSQL_STMT_RETURN:
588 dump_return((PLpgSQL_stmt_return *) stmt);
590 case PLPGSQL_STMT_RETURN_NEXT:
591 dump_return_next((PLpgSQL_stmt_return_next *) stmt);
593 case PLPGSQL_STMT_RETURN_QUERY:
594 dump_return_query((PLpgSQL_stmt_return_query *) stmt);
596 case PLPGSQL_STMT_RAISE:
597 dump_raise((PLpgSQL_stmt_raise *) stmt);
599 case PLPGSQL_STMT_EXECSQL:
600 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
602 case PLPGSQL_STMT_DYNEXECUTE:
603 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
605 case PLPGSQL_STMT_DYNFORS:
606 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
608 case PLPGSQL_STMT_GETDIAG:
609 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
611 case PLPGSQL_STMT_OPEN:
612 dump_open((PLpgSQL_stmt_open *) stmt);
614 case PLPGSQL_STMT_FETCH:
615 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
617 case PLPGSQL_STMT_CLOSE:
618 dump_close((PLpgSQL_stmt_close *) stmt);
620 case PLPGSQL_STMT_PERFORM:
621 dump_perform((PLpgSQL_stmt_perform *) stmt);
624 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
630 dump_stmts(List *stmts)
636 dump_stmt((PLpgSQL_stmt *) lfirst(s));
641 dump_block(PLpgSQL_stmt_block *block)
645 if (block->label == NULL)
651 printf("BLOCK <<%s>>\n", name);
653 dump_stmts(block->body);
655 if (block->exceptions)
659 foreach(e, block->exceptions->exc_list)
661 PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
662 PLpgSQL_condition *cond;
665 printf(" EXCEPTION WHEN ");
666 for (cond = exc->conditions; cond; cond = cond->next)
668 if (cond != exc->conditions)
670 printf("%s", cond->condname);
673 dump_stmts(exc->action);
678 printf(" END -- %s\n", name);
682 dump_assign(PLpgSQL_stmt_assign *stmt)
685 printf("ASSIGN var %d := ", stmt->varno);
686 dump_expr(stmt->expr);
691 dump_if(PLpgSQL_stmt_if *stmt)
695 dump_expr(stmt->cond);
698 dump_stmts(stmt->true_body);
700 if (stmt->false_body != NIL)
704 dump_stmts(stmt->false_body);
712 dump_loop(PLpgSQL_stmt_loop *stmt)
717 dump_stmts(stmt->body);
720 printf(" ENDLOOP\n");
724 dump_while(PLpgSQL_stmt_while *stmt)
728 dump_expr(stmt->cond);
731 dump_stmts(stmt->body);
734 printf(" ENDWHILE\n");
738 dump_fori(PLpgSQL_stmt_fori *stmt)
741 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
746 dump_expr(stmt->lower);
750 dump_expr(stmt->upper);
754 dump_expr(stmt->step);
758 dump_stmts(stmt->body);
761 printf(" ENDFORI\n");
765 dump_fors(PLpgSQL_stmt_fors *stmt)
768 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
769 dump_expr(stmt->query);
772 dump_stmts(stmt->body);
775 printf(" ENDFORS\n");
779 dump_open(PLpgSQL_stmt_open *stmt)
782 printf("OPEN curvar=%d\n", stmt->curvar);
785 if (stmt->argquery != NULL)
788 printf(" arguments = '");
789 dump_expr(stmt->argquery);
792 if (stmt->query != NULL)
795 printf(" query = '");
796 dump_expr(stmt->query);
799 if (stmt->dynquery != NULL)
802 printf(" execute = '");
803 dump_expr(stmt->dynquery);
811 dump_fetch(PLpgSQL_stmt_fetch *stmt)
817 printf("FETCH curvar=%d\n", stmt->curvar);
818 dump_cursor_direction(stmt);
821 if (stmt->rec != NULL)
824 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
826 if (stmt->row != NULL)
829 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
835 printf("MOVE curvar=%d\n", stmt->curvar);
836 dump_cursor_direction(stmt);
841 dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
845 switch (stmt->direction)
851 printf(" BACKWARD ");
854 printf(" ABSOLUTE ");
857 printf(" RELATIVE ");
860 printf("??? unknown cursor direction %d", stmt->direction);
865 dump_expr(stmt->expr);
869 printf("%d\n", stmt->how_many);
875 dump_close(PLpgSQL_stmt_close *stmt)
878 printf("CLOSE curvar=%d\n", stmt->curvar);
882 dump_perform(PLpgSQL_stmt_perform *stmt)
885 printf("PERFORM expr = ");
886 dump_expr(stmt->expr);
891 dump_exit(PLpgSQL_stmt_exit *stmt)
894 printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
895 if (stmt->label != NULL)
896 printf(" label='%s'", stmt->label);
897 if (stmt->cond != NULL)
900 dump_expr(stmt->cond);
906 dump_return(PLpgSQL_stmt_return *stmt)
910 if (stmt->retvarno >= 0)
911 printf("variable %d", stmt->retvarno);
912 else if (stmt->expr != NULL)
913 dump_expr(stmt->expr);
920 dump_return_next(PLpgSQL_stmt_return_next *stmt)
923 printf("RETURN NEXT ");
924 if (stmt->retvarno >= 0)
925 printf("variable %d", stmt->retvarno);
926 else if (stmt->expr != NULL)
927 dump_expr(stmt->expr);
934 dump_return_query(PLpgSQL_stmt_return_query *stmt)
937 printf("RETURN QUERY ");
938 dump_expr(stmt->query);
943 dump_raise(PLpgSQL_stmt_raise *stmt)
949 printf("RAISE '%s'\n", stmt->message);
951 foreach(lc, stmt->params)
954 printf(" parameter %d: ", i++);
955 dump_expr((PLpgSQL_expr *) lfirst(lc));
962 dump_execsql(PLpgSQL_stmt_execsql *stmt)
966 dump_expr(stmt->sqlstmt);
970 if (stmt->rec != NULL)
973 printf(" INTO%s target = %d %s\n",
974 stmt->strict ? " STRICT" : "",
975 stmt->rec->recno, stmt->rec->refname);
977 if (stmt->row != NULL)
980 printf(" INTO%s target = %d %s\n",
981 stmt->strict ? " STRICT" : "",
982 stmt->row->rowno, stmt->row->refname);
988 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
992 dump_expr(stmt->query);
996 if (stmt->rec != NULL)
999 printf(" INTO%s target = %d %s\n",
1000 stmt->strict ? " STRICT" : "",
1001 stmt->rec->recno, stmt->rec->refname);
1003 if (stmt->row != NULL)
1006 printf(" INTO%s target = %d %s\n",
1007 stmt->strict ? " STRICT" : "",
1008 stmt->row->rowno, stmt->row->refname);
1014 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
1017 printf("FORS %s EXECUTE ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
1018 dump_expr(stmt->query);
1021 dump_stmts(stmt->body);
1024 printf(" ENDFORS\n");
1028 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
1033 printf("GET DIAGNOSTICS ");
1034 foreach(lc, stmt->diag_items)
1036 PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1038 if (lc != list_head(stmt->diag_items))
1041 printf("{var %d} = ", diag_item->target);
1043 switch (diag_item->kind)
1045 case PLPGSQL_GETDIAG_ROW_COUNT:
1046 printf("ROW_COUNT");
1049 case PLPGSQL_GETDIAG_RESULT_OID:
1050 printf("RESULT_OID");
1062 dump_expr(PLpgSQL_expr *expr)
1066 printf("'%s", expr->query);
1067 if (expr->nparams > 0)
1070 for (i = 0; i < expr->nparams; i++)
1074 printf("$%d=%d", i + 1, expr->params[i]);
1082 plpgsql_dumptree(PLpgSQL_function *func)
1087 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1090 printf("\nFunction's data area:\n");
1091 for (i = 0; i < func->ndatums; i++)
1093 d = func->datums[i];
1095 printf(" entry %d: ", i);
1098 case PLPGSQL_DTYPE_VAR:
1100 PLpgSQL_var *var = (PLpgSQL_var *) d;
1102 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1103 var->refname, var->datatype->typname,
1104 var->datatype->typoid,
1105 var->datatype->atttypmod);
1107 printf(" CONSTANT\n");
1109 printf(" NOT NULL\n");
1110 if (var->default_val != NULL)
1112 printf(" DEFAULT ");
1113 dump_expr(var->default_val);
1116 if (var->cursor_explicit_expr != NULL)
1118 if (var->cursor_explicit_argrow >= 0)
1119 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1121 printf(" CURSOR IS ");
1122 dump_expr(var->cursor_explicit_expr);
1127 case PLPGSQL_DTYPE_ROW:
1129 PLpgSQL_row *row = (PLpgSQL_row *) d;
1132 printf("ROW %-16s fields", row->refname);
1133 for (i = 0; i < row->nfields; i++)
1135 if (row->fieldnames[i])
1136 printf(" %s=var %d", row->fieldnames[i],
1142 case PLPGSQL_DTYPE_REC:
1143 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
1145 case PLPGSQL_DTYPE_RECFIELD:
1146 printf("RECFIELD %-16s of REC %d\n",
1147 ((PLpgSQL_recfield *) d)->fieldname,
1148 ((PLpgSQL_recfield *) d)->recparentno);
1150 case PLPGSQL_DTYPE_ARRAYELEM:
1151 printf("ARRAYELEM of VAR %d subscript ",
1152 ((PLpgSQL_arrayelem *) d)->arrayparentno);
1153 dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1156 case PLPGSQL_DTYPE_TRIGARG:
1158 dump_expr(((PLpgSQL_trigarg *) d)->argnum);
1162 printf("??? unknown data type %d\n", d->dtype);
1165 printf("\nFunction's statements:\n");
1168 printf("%3d:", func->action->lineno);
1169 dump_block(func->action);
1170 printf("\nEnd of execution tree of function %s\n\n", func->fn_name);