1 /*-------------------------------------------------------------------------
3 * pl_funcs.c - Misc functions for the PL/pgSQL
6 * Portions Copyright (c) 1996-2009, 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.85 2009/11/07 00:52:26 tgl Exp $
13 *-------------------------------------------------------------------------
20 #include "parser/scansup.h"
24 * Local variables for namespace handling
26 * The namespace structure actually forms a tree, of which only one linear
27 * list or "chain" (from the youngest item to the root) is accessible from
28 * any one plpgsql statement. During initial parsing of a function, ns_top
29 * points to the youngest item accessible from the block currently being
30 * parsed. We store the entire tree, however, since at runtime we will need
31 * to access the chain that's relevant to any one statement.
33 * Block boundaries in the namespace chain are marked by PLPGSQL_NSTYPE_LABEL
37 static PLpgSQL_nsitem *ns_top = NULL;
41 * plpgsql_ns_init Initialize namespace processing for a new function
52 * plpgsql_ns_push Create a new namespace level
56 plpgsql_ns_push(const char *label)
60 plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
65 * plpgsql_ns_pop Pop entries back to (and including) the last label
71 Assert(ns_top != NULL);
72 while (ns_top->itemtype != PLPGSQL_NSTYPE_LABEL)
73 ns_top = ns_top->prev;
74 ns_top = ns_top->prev;
79 * plpgsql_ns_top Fetch the current namespace chain end
90 * plpgsql_ns_additem Add an item to the current namespace chain
94 plpgsql_ns_additem(int itemtype, int itemno, const char *name)
99 /* first item added must be a label */
100 Assert(ns_top != NULL || itemtype == PLPGSQL_NSTYPE_LABEL);
102 nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
103 nse->itemtype = itemtype;
104 nse->itemno = itemno;
106 strcpy(nse->name, name);
112 * plpgsql_ns_lookup Lookup an identifier in the given namespace chain
114 * Note that this only searches for variables, not labels.
116 * If localmode is TRUE, only the topmost block level is searched.
118 * name1 must be non-NULL. Pass NULL for name2 and/or name3 if parsing a name
119 * with fewer than three components.
121 * If names_used isn't NULL, *names_used receives the number of names
122 * matched: 0 if no match, 1 if name1 matched an unqualified variable name,
123 * 2 if name1 and name2 matched a block label + variable name.
125 * Note that name3 is never directly matched to anything. However, if it
126 * isn't NULL, we will disregard qualified matches to scalar variables.
127 * Similarly, if name2 isn't NULL, we disregard unqualified matches to
132 plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
133 const char *name1, const char *name2, const char *name3,
136 /* Outer loop iterates once per block level in the namespace chain */
137 while (ns_cur != NULL)
139 PLpgSQL_nsitem *nsitem;
141 /* Check this level for unqualified match to variable name */
142 for (nsitem = ns_cur;
143 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
144 nsitem = nsitem->prev)
146 if (strcmp(nsitem->name, name1) == 0)
149 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
158 /* Check this level for qualified match to variable name */
160 strcmp(nsitem->name, name1) == 0)
162 for (nsitem = ns_cur;
163 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
164 nsitem = nsitem->prev)
166 if (strcmp(nsitem->name, name2) == 0)
169 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
180 break; /* do not look into upper levels */
182 ns_cur = nsitem->prev;
185 /* This is just to suppress possibly-uninitialized-variable warnings */
188 return NULL; /* No match found */
193 * plpgsql_ns_lookup_label Lookup a label in the given namespace chain
197 plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name)
199 while (ns_cur != NULL)
201 if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
202 strcmp(ns_cur->name, name) == 0)
204 ns_cur = ns_cur->prev;
207 return NULL; /* label not found */
212 * plpgsql_convert_ident
214 * Convert a possibly-qualified identifier to internal form: handle
215 * double quotes, translate to lower case where not inside quotes,
216 * truncate to NAMEDATALEN.
218 * There may be several identifiers separated by dots and optional
219 * whitespace. Each one is converted to a separate palloc'd string.
220 * The caller passes the expected number of identifiers, as well as
221 * a char* array to hold them. It is an error if we find the wrong
222 * number of identifiers (cf grammar processing of fori_varname).
224 * NOTE: the input string has already been accepted by the flex lexer,
225 * so we don't need a heckuva lot of error checking here.
229 plpgsql_convert_ident(const char *s, char **output, int numidents)
231 const char *sstart = s;
234 /* Outer loop over identifiers */
240 /* Process current identifier */
244 /* Quoted identifier: copy, collapsing out doubled quotes */
246 curident = palloc(strlen(s) + 1); /* surely enough room */
259 if (*s != '"') /* should not happen if lexer checked */
261 (errcode(ERRCODE_SYNTAX_ERROR),
262 errmsg("unterminated \" in identifier: %s", sstart)));
265 /* Truncate to NAMEDATALEN */
266 truncate_identifier(curident, cp - curident, false);
270 /* Normal identifier: extends till dot or whitespace */
271 const char *thisstart = s;
273 while (*s && *s != '.' && !scanner_isspace(*s))
275 /* Downcase and truncate to NAMEDATALEN */
276 curident = downcase_truncate_identifier(thisstart, s - thisstart,
280 /* Pass ident to caller */
281 if (identctr < numidents)
282 output[identctr++] = curident;
285 (errcode(ERRCODE_SYNTAX_ERROR),
286 errmsg("qualified identifier cannot be used here: %s",
289 /* If not done, skip whitespace, dot, whitespace */
292 while (*s && scanner_isspace(*s))
295 elog(ERROR, "expected dot between identifiers: %s", sstart);
296 while (*s && scanner_isspace(*s))
299 elog(ERROR, "expected another identifier: %s", sstart);
303 if (identctr != numidents)
304 elog(ERROR, "improperly qualified identifier: %s",
310 * Statement type as a string, for use in error messages etc.
313 plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
315 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
317 case PLPGSQL_STMT_BLOCK:
318 return _("statement block");
319 case PLPGSQL_STMT_ASSIGN:
320 return _("assignment");
321 case PLPGSQL_STMT_IF:
323 case PLPGSQL_STMT_CASE:
325 case PLPGSQL_STMT_LOOP:
327 case PLPGSQL_STMT_WHILE:
329 case PLPGSQL_STMT_FORI:
330 return _("FOR with integer loop variable");
331 case PLPGSQL_STMT_FORS:
332 return _("FOR over SELECT rows");
333 case PLPGSQL_STMT_FORC:
334 return _("FOR over cursor");
335 case PLPGSQL_STMT_EXIT:
337 case PLPGSQL_STMT_RETURN:
339 case PLPGSQL_STMT_RETURN_NEXT:
340 return "RETURN NEXT";
341 case PLPGSQL_STMT_RETURN_QUERY:
342 return "RETURN QUERY";
343 case PLPGSQL_STMT_RAISE:
345 case PLPGSQL_STMT_EXECSQL:
346 return _("SQL statement");
347 case PLPGSQL_STMT_DYNEXECUTE:
348 return _("EXECUTE statement");
349 case PLPGSQL_STMT_DYNFORS:
350 return _("FOR over EXECUTE statement");
351 case PLPGSQL_STMT_GETDIAG:
352 return "GET DIAGNOSTICS";
353 case PLPGSQL_STMT_OPEN:
355 case PLPGSQL_STMT_FETCH:
357 case PLPGSQL_STMT_CLOSE:
359 case PLPGSQL_STMT_PERFORM:
367 /**********************************************************************
368 * Debug functions for analyzing the compiled code
369 **********************************************************************/
370 static int dump_indent;
372 static void dump_ind(void);
373 static void dump_stmt(PLpgSQL_stmt *stmt);
374 static void dump_block(PLpgSQL_stmt_block *block);
375 static void dump_assign(PLpgSQL_stmt_assign *stmt);
376 static void dump_if(PLpgSQL_stmt_if *stmt);
377 static void dump_case(PLpgSQL_stmt_case *stmt);
378 static void dump_loop(PLpgSQL_stmt_loop *stmt);
379 static void dump_while(PLpgSQL_stmt_while *stmt);
380 static void dump_fori(PLpgSQL_stmt_fori *stmt);
381 static void dump_fors(PLpgSQL_stmt_fors *stmt);
382 static void dump_forc(PLpgSQL_stmt_forc *stmt);
383 static void dump_exit(PLpgSQL_stmt_exit *stmt);
384 static void dump_return(PLpgSQL_stmt_return *stmt);
385 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
386 static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
387 static void dump_raise(PLpgSQL_stmt_raise *stmt);
388 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
389 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
390 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
391 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
392 static void dump_open(PLpgSQL_stmt_open *stmt);
393 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
394 static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt);
395 static void dump_close(PLpgSQL_stmt_close *stmt);
396 static void dump_perform(PLpgSQL_stmt_perform *stmt);
397 static void dump_expr(PLpgSQL_expr *expr);
405 for (i = 0; i < dump_indent; i++)
410 dump_stmt(PLpgSQL_stmt *stmt)
412 printf("%3d:", stmt->lineno);
413 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
415 case PLPGSQL_STMT_BLOCK:
416 dump_block((PLpgSQL_stmt_block *) stmt);
418 case PLPGSQL_STMT_ASSIGN:
419 dump_assign((PLpgSQL_stmt_assign *) stmt);
421 case PLPGSQL_STMT_IF:
422 dump_if((PLpgSQL_stmt_if *) stmt);
424 case PLPGSQL_STMT_CASE:
425 dump_case((PLpgSQL_stmt_case *) stmt);
427 case PLPGSQL_STMT_LOOP:
428 dump_loop((PLpgSQL_stmt_loop *) stmt);
430 case PLPGSQL_STMT_WHILE:
431 dump_while((PLpgSQL_stmt_while *) stmt);
433 case PLPGSQL_STMT_FORI:
434 dump_fori((PLpgSQL_stmt_fori *) stmt);
436 case PLPGSQL_STMT_FORS:
437 dump_fors((PLpgSQL_stmt_fors *) stmt);
439 case PLPGSQL_STMT_FORC:
440 dump_forc((PLpgSQL_stmt_forc *) stmt);
442 case PLPGSQL_STMT_EXIT:
443 dump_exit((PLpgSQL_stmt_exit *) stmt);
445 case PLPGSQL_STMT_RETURN:
446 dump_return((PLpgSQL_stmt_return *) stmt);
448 case PLPGSQL_STMT_RETURN_NEXT:
449 dump_return_next((PLpgSQL_stmt_return_next *) stmt);
451 case PLPGSQL_STMT_RETURN_QUERY:
452 dump_return_query((PLpgSQL_stmt_return_query *) stmt);
454 case PLPGSQL_STMT_RAISE:
455 dump_raise((PLpgSQL_stmt_raise *) stmt);
457 case PLPGSQL_STMT_EXECSQL:
458 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
460 case PLPGSQL_STMT_DYNEXECUTE:
461 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
463 case PLPGSQL_STMT_DYNFORS:
464 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
466 case PLPGSQL_STMT_GETDIAG:
467 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
469 case PLPGSQL_STMT_OPEN:
470 dump_open((PLpgSQL_stmt_open *) stmt);
472 case PLPGSQL_STMT_FETCH:
473 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
475 case PLPGSQL_STMT_CLOSE:
476 dump_close((PLpgSQL_stmt_close *) stmt);
478 case PLPGSQL_STMT_PERFORM:
479 dump_perform((PLpgSQL_stmt_perform *) stmt);
482 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
488 dump_stmts(List *stmts)
494 dump_stmt((PLpgSQL_stmt *) lfirst(s));
499 dump_block(PLpgSQL_stmt_block *block)
503 if (block->label == NULL)
509 printf("BLOCK <<%s>>\n", name);
511 dump_stmts(block->body);
513 if (block->exceptions)
517 foreach(e, block->exceptions->exc_list)
519 PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
520 PLpgSQL_condition *cond;
523 printf(" EXCEPTION WHEN ");
524 for (cond = exc->conditions; cond; cond = cond->next)
526 if (cond != exc->conditions)
528 printf("%s", cond->condname);
531 dump_stmts(exc->action);
536 printf(" END -- %s\n", name);
540 dump_assign(PLpgSQL_stmt_assign *stmt)
543 printf("ASSIGN var %d := ", stmt->varno);
544 dump_expr(stmt->expr);
549 dump_if(PLpgSQL_stmt_if *stmt)
553 dump_expr(stmt->cond);
556 dump_stmts(stmt->true_body);
558 if (stmt->false_body != NIL)
562 dump_stmts(stmt->false_body);
570 dump_case(PLpgSQL_stmt_case *stmt)
575 printf("CASE %d ", stmt->t_varno);
577 dump_expr(stmt->t_expr);
580 foreach(l, stmt->case_when_list)
582 PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
586 dump_expr(cwt->expr);
591 dump_stmts(cwt->stmts);
599 dump_stmts(stmt->else_stmts);
604 printf(" ENDCASE\n");
608 dump_loop(PLpgSQL_stmt_loop *stmt)
613 dump_stmts(stmt->body);
616 printf(" ENDLOOP\n");
620 dump_while(PLpgSQL_stmt_while *stmt)
624 dump_expr(stmt->cond);
627 dump_stmts(stmt->body);
630 printf(" ENDWHILE\n");
634 dump_fori(PLpgSQL_stmt_fori *stmt)
637 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
642 dump_expr(stmt->lower);
646 dump_expr(stmt->upper);
650 dump_expr(stmt->step);
654 dump_stmts(stmt->body);
657 printf(" ENDFORI\n");
661 dump_fors(PLpgSQL_stmt_fors *stmt)
664 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
665 dump_expr(stmt->query);
668 dump_stmts(stmt->body);
671 printf(" ENDFORS\n");
675 dump_forc(PLpgSQL_stmt_forc *stmt)
678 printf("FORC %s ", stmt->rec->refname);
679 printf("curvar=%d\n", stmt->curvar);
682 if (stmt->argquery != NULL)
685 printf(" arguments = ");
686 dump_expr(stmt->argquery);
691 dump_stmts(stmt->body);
694 printf(" ENDFORC\n");
698 dump_open(PLpgSQL_stmt_open *stmt)
701 printf("OPEN curvar=%d\n", stmt->curvar);
704 if (stmt->argquery != NULL)
707 printf(" arguments = '");
708 dump_expr(stmt->argquery);
711 if (stmt->query != NULL)
714 printf(" query = '");
715 dump_expr(stmt->query);
718 if (stmt->dynquery != NULL)
721 printf(" execute = '");
722 dump_expr(stmt->dynquery);
730 dump_fetch(PLpgSQL_stmt_fetch *stmt)
736 printf("FETCH curvar=%d\n", stmt->curvar);
737 dump_cursor_direction(stmt);
740 if (stmt->rec != NULL)
743 printf(" target = %d %s\n", stmt->rec->dno, stmt->rec->refname);
745 if (stmt->row != NULL)
748 printf(" target = %d %s\n", stmt->row->dno, stmt->row->refname);
754 printf("MOVE curvar=%d\n", stmt->curvar);
755 dump_cursor_direction(stmt);
760 dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
764 switch (stmt->direction)
770 printf(" BACKWARD ");
773 printf(" ABSOLUTE ");
776 printf(" RELATIVE ");
779 printf("??? unknown cursor direction %d", stmt->direction);
784 dump_expr(stmt->expr);
788 printf("%ld\n", stmt->how_many);
794 dump_close(PLpgSQL_stmt_close *stmt)
797 printf("CLOSE curvar=%d\n", stmt->curvar);
801 dump_perform(PLpgSQL_stmt_perform *stmt)
804 printf("PERFORM expr = ");
805 dump_expr(stmt->expr);
810 dump_exit(PLpgSQL_stmt_exit *stmt)
813 printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
814 if (stmt->label != NULL)
815 printf(" label='%s'", stmt->label);
816 if (stmt->cond != NULL)
819 dump_expr(stmt->cond);
825 dump_return(PLpgSQL_stmt_return *stmt)
829 if (stmt->retvarno >= 0)
830 printf("variable %d", stmt->retvarno);
831 else if (stmt->expr != NULL)
832 dump_expr(stmt->expr);
839 dump_return_next(PLpgSQL_stmt_return_next *stmt)
842 printf("RETURN NEXT ");
843 if (stmt->retvarno >= 0)
844 printf("variable %d", stmt->retvarno);
845 else if (stmt->expr != NULL)
846 dump_expr(stmt->expr);
853 dump_return_query(PLpgSQL_stmt_return_query *stmt)
858 printf("RETURN QUERY ");
859 dump_expr(stmt->query);
864 printf("RETURN QUERY EXECUTE ");
865 dump_expr(stmt->dynquery);
867 if (stmt->params != NIL)
877 foreach(lc, stmt->params)
880 printf(" parameter $%d: ", i++);
881 dump_expr((PLpgSQL_expr *) lfirst(lc));
890 dump_raise(PLpgSQL_stmt_raise *stmt)
896 printf("RAISE level=%d", stmt->elog_level);
898 printf(" condname='%s'", stmt->condname);
900 printf(" message='%s'", stmt->message);
903 foreach(lc, stmt->params)
906 printf(" parameter %d: ", i++);
907 dump_expr((PLpgSQL_expr *) lfirst(lc));
915 foreach(lc, stmt->options)
917 PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
920 switch (opt->opt_type)
922 case PLPGSQL_RAISEOPTION_ERRCODE:
923 printf(" ERRCODE = ");
925 case PLPGSQL_RAISEOPTION_MESSAGE:
926 printf(" MESSAGE = ");
928 case PLPGSQL_RAISEOPTION_DETAIL:
929 printf(" DETAIL = ");
931 case PLPGSQL_RAISEOPTION_HINT:
935 dump_expr(opt->expr);
944 dump_execsql(PLpgSQL_stmt_execsql *stmt)
948 dump_expr(stmt->sqlstmt);
952 if (stmt->rec != NULL)
955 printf(" INTO%s target = %d %s\n",
956 stmt->strict ? " STRICT" : "",
957 stmt->rec->dno, stmt->rec->refname);
959 if (stmt->row != NULL)
962 printf(" INTO%s target = %d %s\n",
963 stmt->strict ? " STRICT" : "",
964 stmt->row->dno, stmt->row->refname);
970 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
974 dump_expr(stmt->query);
978 if (stmt->rec != NULL)
981 printf(" INTO%s target = %d %s\n",
982 stmt->strict ? " STRICT" : "",
983 stmt->rec->dno, stmt->rec->refname);
985 if (stmt->row != NULL)
988 printf(" INTO%s target = %d %s\n",
989 stmt->strict ? " STRICT" : "",
990 stmt->row->dno, stmt->row->refname);
992 if (stmt->params != NIL)
1001 foreach(lc, stmt->params)
1004 printf(" parameter %d: ", i++);
1005 dump_expr((PLpgSQL_expr *) lfirst(lc));
1014 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
1017 printf("FORS %s EXECUTE ",
1018 (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
1019 dump_expr(stmt->query);
1021 if (stmt->params != NIL)
1031 foreach(lc, stmt->params)
1034 printf(" parameter $%d: ", i++);
1035 dump_expr((PLpgSQL_expr *) lfirst(lc));
1040 dump_stmts(stmt->body);
1042 printf(" ENDFORS\n");
1046 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
1051 printf("GET DIAGNOSTICS ");
1052 foreach(lc, stmt->diag_items)
1054 PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1056 if (lc != list_head(stmt->diag_items))
1059 printf("{var %d} = ", diag_item->target);
1061 switch (diag_item->kind)
1063 case PLPGSQL_GETDIAG_ROW_COUNT:
1064 printf("ROW_COUNT");
1067 case PLPGSQL_GETDIAG_RESULT_OID:
1068 printf("RESULT_OID");
1080 dump_expr(PLpgSQL_expr *expr)
1082 printf("'%s'", expr->query);
1086 plpgsql_dumptree(PLpgSQL_function *func)
1091 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1094 printf("\nFunction's data area:\n");
1095 for (i = 0; i < func->ndatums; i++)
1097 d = func->datums[i];
1099 printf(" entry %d: ", i);
1102 case PLPGSQL_DTYPE_VAR:
1104 PLpgSQL_var *var = (PLpgSQL_var *) d;
1106 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1107 var->refname, var->datatype->typname,
1108 var->datatype->typoid,
1109 var->datatype->atttypmod);
1111 printf(" CONSTANT\n");
1113 printf(" NOT NULL\n");
1114 if (var->default_val != NULL)
1116 printf(" DEFAULT ");
1117 dump_expr(var->default_val);
1120 if (var->cursor_explicit_expr != NULL)
1122 if (var->cursor_explicit_argrow >= 0)
1123 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1125 printf(" CURSOR IS ");
1126 dump_expr(var->cursor_explicit_expr);
1131 case PLPGSQL_DTYPE_ROW:
1133 PLpgSQL_row *row = (PLpgSQL_row *) d;
1136 printf("ROW %-16s fields", row->refname);
1137 for (i = 0; i < row->nfields; i++)
1139 if (row->fieldnames[i])
1140 printf(" %s=var %d", row->fieldnames[i],
1146 case PLPGSQL_DTYPE_REC:
1147 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
1149 case PLPGSQL_DTYPE_RECFIELD:
1150 printf("RECFIELD %-16s of REC %d\n",
1151 ((PLpgSQL_recfield *) d)->fieldname,
1152 ((PLpgSQL_recfield *) d)->recparentno);
1154 case PLPGSQL_DTYPE_ARRAYELEM:
1155 printf("ARRAYELEM of VAR %d subscript ",
1156 ((PLpgSQL_arrayelem *) d)->arrayparentno);
1157 dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1161 printf("??? unknown data type %d\n", d->dtype);
1164 printf("\nFunction's statements:\n");
1167 printf("%3d:", func->action->lineno);
1168 dump_block(func->action);
1169 printf("\nEnd of execution tree of function %s\n\n", func->fn_name);