+ /* \sf -- show a function's source code */
+ else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
+ {
+ bool show_linenumbers = (strcmp(cmd, "sf+") == 0);
+ PQExpBuffer func_buf;
+ char *func;
+ Oid foid = InvalidOid;
+
+ func_buf = createPQExpBuffer();
+ func = psql_scan_slash_option(scan_state,
+ OT_WHOLE_LINE, NULL, true);
+ if (!func)
+ {
+ psql_error("function name is required\n");
+ status = PSQL_CMD_ERROR;
+ }
+ else if (!lookup_function_oid(pset.db, func, &foid))
+ {
+ /* error already reported */
+ status = PSQL_CMD_ERROR;
+ }
+ else if (!get_create_function_cmd(pset.db, foid, func_buf))
+ {
+ /* error already reported */
+ status = PSQL_CMD_ERROR;
+ }
+ else
+ {
+ FILE *output;
+ bool is_pager;
+
+ /* Select output stream: stdout, pager, or file */
+ if (pset.queryFout == stdout)
+ {
+ /* count lines in function to see if pager is needed */
+ int lineno = 0;
+ const char *lines = func_buf->data;
+
+ while (*lines != '\0')
+ {
+ lineno++;
+ /* find start of next line */
+ lines = strchr(lines, '\n');
+ if (!lines)
+ break;
+ lines++;
+ }
+
+ output = PageOutput(lineno, pset.popt.topt.pager);
+ is_pager = true;
+ }
+ else
+ {
+ /* use previously set output file, without pager */
+ output = pset.queryFout;
+ is_pager = false;
+ }
+
+ if (show_linenumbers)
+ {
+ bool in_header = true;
+ int lineno = 0;
+ char *lines = func_buf->data;
+
+ /*
+ * lineno "1" should correspond to the first line of the
+ * function body. We expect that pg_get_functiondef() will
+ * emit that on a line beginning with "AS ", and that there
+ * can be no such line before the real start of the function
+ * body.
+ *
+ * Note that this loop scribbles on func_buf.
+ */
+ while (*lines != '\0')
+ {
+ char *eol;
+
+ if (in_header && strncmp(lines, "AS ", 3) == 0)
+ in_header = false;
+ /* increment lineno only for body's lines */
+ if (!in_header)
+ lineno++;
+
+ /* find and mark end of current line */
+ eol = strchr(lines, '\n');
+ if (eol != NULL)
+ *eol = '\0';
+
+ /* show current line as appropriate */
+ if (in_header)
+ fprintf(output, " %s\n", lines);
+ else
+ fprintf(output, "%-7d %s\n", lineno, lines);
+
+ /* advance to next line, if any */
+ if (eol == NULL)
+ break;
+ lines = ++eol;
+ }
+ }
+ else
+ {
+ /* just send the function definition to output */
+ fputs(func_buf->data, output);
+ }
+
+ if (is_pager)
+ ClosePager(output);
+ }
+
+ if (func)
+ free(func);
+ destroyPQExpBuffer(func_buf);
+ }
+