|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* profile.c - gawk bytecode pretty-printer with counts
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* Copyright (C) 1999-2017 the Free Software Foundation, Inc.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* This file is part of GAWK, the GNU implementation of the
|
|
Packit |
575503 |
* AWK Programming Language.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* GAWK is free software; you can redistribute it and/or modify
|
|
Packit |
575503 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
575503 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit |
575503 |
* (at your option) any later version.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* GAWK is distributed in the hope that it will be useful,
|
|
Packit |
575503 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
575503 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
575503 |
* GNU General Public License for more details.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
575503 |
* along with this program; if not, write to the Free Software
|
|
Packit |
575503 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
#include "awk.h"
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags);
|
|
Packit |
575503 |
static INSTRUCTION *end_line(INSTRUCTION *ip);
|
|
Packit |
575503 |
static void pp_parenthesize(NODE *n);
|
|
Packit |
575503 |
static void parenthesize(int type, NODE *left, NODE *right);
|
|
Packit |
575503 |
static char *pp_list(int nargs, const char *paren, const char *delim);
|
|
Packit |
575503 |
static char *pp_group3(const char *s1, const char *s2, const char *s3);
|
|
Packit |
575503 |
static char *pp_concat(int nargs);
|
|
Packit |
575503 |
static char *pp_string_or_typed_regex(const char *in_str, size_t len, int delim, bool typed_regex);
|
|
Packit |
575503 |
static char *pp_typed_regex(const char *in_str, size_t len, int delim);
|
|
Packit |
575503 |
static bool is_binary(int type);
|
|
Packit |
575503 |
static bool is_scalar(int type);
|
|
Packit |
575503 |
static int prec_level(int type);
|
|
Packit |
575503 |
static void pp_push(int type, char *s, int flag);
|
|
Packit |
575503 |
static NODE *pp_pop(void);
|
|
Packit |
575503 |
static void print_comment(INSTRUCTION *pc, long in);
|
|
Packit |
575503 |
const char *redir2str(int redirtype);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
#define pp_str vname
|
|
Packit |
575503 |
#define pp_len sub.nodep.reserved
|
|
Packit |
575503 |
#define pp_next rnode
|
|
Packit |
575503 |
|
|
Packit |
575503 |
#define DONT_FREE 1
|
|
Packit |
575503 |
#define CAN_FREE 2
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void dump_and_exit(int signum) ATTRIBUTE_NORETURN;
|
|
Packit |
575503 |
static void just_dump(int signum);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pretty printing related functions and variables */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static NODE *pp_stack = NULL;
|
|
Packit |
575503 |
static NODE *func_params; /* function parameters */
|
|
Packit |
575503 |
static FILE *prof_fp; /* where to send the profile */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static long indent_level = 0;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
#define SPACEOVER 0
|
|
Packit |
575503 |
|
|
Packit |
575503 |
#define NO_PPRINT_FLAGS 0
|
|
Packit |
575503 |
#define IN_FOR_HEADER 1
|
|
Packit |
575503 |
#define IN_ELSE_IF 2
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* set_prof_file --- set the output file for profiling or pretty-printing */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
void
|
|
Packit |
575503 |
set_prof_file(const char *file)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
int fd;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
assert(file != NULL);
|
|
Packit |
575503 |
fd = devopen_simple(file, "w", true);
|
|
Packit |
575503 |
if (fd == INVALID_HANDLE)
|
|
Packit |
575503 |
prof_fp = NULL;
|
|
Packit |
575503 |
else if (fd == fileno(stdout))
|
|
Packit |
575503 |
prof_fp = stdout;
|
|
Packit |
575503 |
else if (fd == fileno(stderr))
|
|
Packit |
575503 |
prof_fp = stderr;
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
prof_fp = fdopen(fd, "w");
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (prof_fp == NULL) {
|
|
Packit |
575503 |
/* don't leak file descriptors */
|
|
Packit |
575503 |
int e = errno;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if ( fd != INVALID_HANDLE
|
|
Packit |
575503 |
&& fd != fileno(stdout)
|
|
Packit |
575503 |
&& fd != fileno(stderr))
|
|
Packit |
575503 |
(void) close(fd);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
errno = e;
|
|
Packit |
575503 |
warning(_("could not open `%s' for writing: %s"),
|
|
Packit |
575503 |
file, strerror(errno));
|
|
Packit |
575503 |
warning(_("sending profile to standard error"));
|
|
Packit |
575503 |
prof_fp = stderr;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* init_profiling_signals --- set up signal handling for gawk --profile */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
void
|
|
Packit |
575503 |
init_profiling_signals()
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
#ifdef __DJGPP__
|
|
Packit |
575503 |
signal(SIGINT, dump_and_exit);
|
|
Packit |
575503 |
signal(SIGQUIT, just_dump);
|
|
Packit |
575503 |
#else /* !__DJGPP__ */
|
|
Packit |
575503 |
#ifdef SIGHUP
|
|
Packit |
575503 |
signal(SIGHUP, dump_and_exit);
|
|
Packit |
575503 |
#endif
|
|
Packit |
575503 |
#ifdef SIGUSR1
|
|
Packit |
575503 |
signal(SIGUSR1, just_dump);
|
|
Packit |
575503 |
#endif
|
|
Packit |
575503 |
#endif /* !__DJGPP__ */
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* indent --- print out enough tabs */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
indent(long count)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
int i;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (do_profile) {
|
|
Packit |
575503 |
if (count == 0)
|
|
Packit |
575503 |
fprintf(prof_fp, "\t");
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
fprintf(prof_fp, "%6ld ", count);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
assert(indent_level >= 0);
|
|
Packit |
575503 |
for (i = 0; i < indent_level; i++)
|
|
Packit |
575503 |
fprintf(prof_fp, "\t");
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* indent_in --- increase the level, with error checking */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
indent_in(void)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
assert(indent_level >= 0);
|
|
Packit |
575503 |
indent_level++;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* indent_out --- decrease the level, with error checking */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
indent_out(void)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
indent_level--;
|
|
Packit |
575503 |
assert(indent_level >= 0);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_push --- push a pretty printed string onto the stack */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
pp_push(int type, char *s, int flag)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
NODE *n;
|
|
Packit |
575503 |
getnode(n);
|
|
Packit |
575503 |
n->pp_str = s;
|
|
Packit |
575503 |
n->pp_len = strlen(s);
|
|
Packit |
575503 |
n->flags = flag;
|
|
Packit |
575503 |
n->type = type;
|
|
Packit |
575503 |
n->pp_next = pp_stack;
|
|
Packit |
575503 |
pp_stack = n;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_pop --- pop a pretty printed string off the stack */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static NODE *
|
|
Packit |
575503 |
pp_pop()
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
NODE *n;
|
|
Packit |
575503 |
n = pp_stack;
|
|
Packit |
575503 |
pp_stack = n->pp_next;
|
|
Packit |
575503 |
return n;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_free --- release a pretty printed node */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
pp_free(NODE *n)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
if ((n->flags & CAN_FREE) != 0)
|
|
Packit |
575503 |
efree(n->pp_str);
|
|
Packit |
575503 |
freenode(n);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pprint --- pretty print a program segment */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
INSTRUCTION *pc;
|
|
Packit |
575503 |
NODE *t1;
|
|
Packit |
575503 |
char *str;
|
|
Packit |
575503 |
NODE *t2;
|
|
Packit |
575503 |
INSTRUCTION *ip1;
|
|
Packit |
575503 |
INSTRUCTION *ip2;
|
|
Packit |
575503 |
NODE *m;
|
|
Packit |
575503 |
char *tmp;
|
|
Packit |
575503 |
int rule;
|
|
Packit |
575503 |
static int rule_count[MAXRULE];
|
|
Packit |
575503 |
static bool skip_comment = false;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
for (pc = startp; pc != endp; pc = pc->nexti) {
|
|
Packit |
575503 |
if (pc->source_line > 0)
|
|
Packit |
575503 |
sourceline = pc->source_line;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* skip leading EOL comment as it has already been printed */
|
|
Packit |
575503 |
if (pc->opcode == Op_comment
|
|
Packit |
575503 |
&& pc->memory->comment_type == EOL_COMMENT
|
|
Packit |
575503 |
&& skip_comment) {
|
|
Packit |
575503 |
skip_comment = false;
|
|
Packit |
575503 |
continue;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
skip_comment = false;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
switch (pc->opcode) {
|
|
Packit |
575503 |
case Op_rule:
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* Rules are three instructions long.
|
|
Packit |
575503 |
* See append_rule in awkgram.y.
|
|
Packit |
575503 |
* The first has the Rule Op Code, nexti etc.
|
|
Packit |
575503 |
* The second, (pc + 1) has firsti and lasti:
|
|
Packit |
575503 |
* the first/last ACTION instructions for this rule.
|
|
Packit |
575503 |
* The third has first_line and last_line:
|
|
Packit |
575503 |
* the first and last source line numbers.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
source = pc->source_file;
|
|
Packit |
575503 |
rule = pc->in_rule;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (rule != Rule) {
|
|
Packit |
575503 |
/* Allow for pre-non-rule-block comment */
|
|
Packit |
575503 |
if (pc->nexti != (pc +1)->firsti
|
|
Packit |
575503 |
&& pc->nexti->opcode == Op_comment
|
|
Packit |
575503 |
&& pc->nexti->memory->comment_type == FULL_COMMENT)
|
|
Packit |
575503 |
print_comment(pc->nexti, -1);
|
|
Packit |
575503 |
ip1 = (pc + 1)->firsti;
|
|
Packit |
575503 |
ip2 = (pc + 1)->lasti;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (do_profile) {
|
|
Packit |
575503 |
if (! rule_count[rule]++)
|
|
Packit |
575503 |
fprintf(prof_fp, _("\t# %s rule(s)\n\n"), ruletab[rule]);
|
|
Packit |
575503 |
indent(0);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
fprintf(prof_fp, "%s {", ruletab[rule]);
|
|
Packit |
575503 |
end_line(pc);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
if (do_profile && ! rule_count[rule]++)
|
|
Packit |
575503 |
fprintf(prof_fp, _("\t# Rule(s)\n\n"));
|
|
Packit |
575503 |
ip1 = pc->nexti;
|
|
Packit |
575503 |
indent(ip1->exec_count);
|
|
Packit |
575503 |
if (ip1 != (pc + 1)->firsti) { /* non-empty pattern */
|
|
Packit |
575503 |
pprint(ip1->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
/* Allow for case where the "pattern" is just a comment */
|
|
Packit |
575503 |
if (ip1->nexti->nexti->nexti != (pc +1)->firsti
|
|
Packit |
575503 |
|| ip1->nexti->opcode != Op_comment) {
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s {", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
fprintf(prof_fp, "{");
|
|
Packit |
575503 |
ip1 = (pc + 1)->firsti;
|
|
Packit |
575503 |
ip2 = (pc + 1)->lasti;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (do_profile && ip1->exec_count > 0)
|
|
Packit |
575503 |
fprintf(prof_fp, " # %ld", ip1->exec_count);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
end_line(ip1);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
fprintf(prof_fp, "{\n");
|
|
Packit |
575503 |
ip1 = (pc + 1)->firsti;
|
|
Packit |
575503 |
ip2 = (pc + 1)->lasti;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
ip1 = ip1->nexti;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(ip1, ip2, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
if (do_profile)
|
|
Packit |
575503 |
indent(0);
|
|
Packit |
575503 |
fprintf(prof_fp, "}\n\n");
|
|
Packit |
575503 |
pc = (pc + 1)->lasti;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_atexit:
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_stop:
|
|
Packit |
575503 |
memset(rule_count, 0, MAXRULE * sizeof(int));
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_push_i:
|
|
Packit |
575503 |
m = pc->memory;
|
|
Packit |
575503 |
if (m == Nnull_string) /* optional return or exit value; don't print 0 or "" */
|
|
Packit |
575503 |
pp_push(pc->opcode, m->stptr, DONT_FREE);
|
|
Packit |
575503 |
else if ((m->flags & NUMBER) != 0)
|
|
Packit |
575503 |
pp_push(pc->opcode, pp_number(m), CAN_FREE);
|
|
Packit |
575503 |
else {
|
|
Packit |
575503 |
str = pp_string(m->stptr, m->stlen, '"');
|
|
Packit |
575503 |
if ((m->flags & INTLSTR) != 0) {
|
|
Packit |
575503 |
char *tmp = str;
|
|
Packit |
575503 |
str = pp_group3("_", tmp, "");
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_store_var:
|
|
Packit |
575503 |
if (pc->initval != NULL)
|
|
Packit |
575503 |
pp_push(Op_push_i, pp_node(pc->initval), CAN_FREE);
|
|
Packit |
575503 |
/* fall through */
|
|
Packit |
575503 |
case Op_store_sub:
|
|
Packit |
575503 |
case Op_assign_concat:
|
|
Packit |
575503 |
case Op_push_lhs:
|
|
Packit |
575503 |
case Op_push_param:
|
|
Packit |
575503 |
case Op_push_array:
|
|
Packit |
575503 |
case Op_push:
|
|
Packit |
575503 |
case Op_push_arg:
|
|
Packit |
575503 |
case Op_push_arg_untyped:
|
|
Packit |
575503 |
m = pc->memory;
|
|
Packit |
575503 |
switch (m->type) {
|
|
Packit |
575503 |
case Node_param_list:
|
|
Packit |
575503 |
pp_push(pc->opcode, func_params[m->param_cnt].param, DONT_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Node_var:
|
|
Packit |
575503 |
case Node_var_new:
|
|
Packit |
575503 |
case Node_var_array:
|
|
Packit |
575503 |
if (m->vname != NULL)
|
|
Packit |
575503 |
pp_push(pc->opcode, m->vname, DONT_FREE);
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
fatal(_("internal error: %s with null vname"),
|
|
Packit |
575503 |
nodetype2str(m->type));
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
cant_happen();
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
switch (pc->opcode) {
|
|
Packit |
575503 |
case Op_store_var:
|
|
Packit |
575503 |
t2 = pp_pop(); /* l.h.s. */
|
|
Packit |
575503 |
t1 = pp_pop(); /* r.h.s. */
|
|
Packit |
575503 |
fprintf(prof_fp, "%s%s%s", t2->pp_str, op2str(pc->opcode), t1->pp_str);
|
|
Packit |
575503 |
goto cleanup;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_store_sub:
|
|
Packit |
575503 |
t1 = pp_pop(); /* array */
|
|
Packit |
575503 |
tmp = pp_list(pc->expr_count, op2str(Op_subscript), ", "); /*subscript*/
|
|
Packit |
575503 |
t2 = pp_pop(); /* r.h.s. */
|
|
Packit |
575503 |
fprintf(prof_fp, "%s%s%s%s", t1->pp_str, tmp,
|
|
Packit |
575503 |
op2str(pc->opcode), t2->pp_str);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
goto cleanup;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_assign_concat:
|
|
Packit |
575503 |
t2 = pp_pop(); /* l.h.s. */
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
tmp = pp_group3(t2->pp_str, op2str(Op_concat), t1->pp_str);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s%s%s", t2->pp_str, op2str(Op_assign), tmp);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
cleanup:
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
if ((flags & IN_FOR_HEADER) == 0)
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_sub_array:
|
|
Packit |
575503 |
case Op_subscript_lhs:
|
|
Packit |
575503 |
case Op_subscript:
|
|
Packit |
575503 |
tmp = pp_list(pc->sub_count, op2str(pc->opcode), ", ");
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, tmp, "");
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_and:
|
|
Packit |
575503 |
case Op_or:
|
|
Packit |
575503 |
pprint(pc->nexti, pc->target_jmp, flags);
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
parenthesize(pc->opcode, t1, t2);
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
pc = pc->target_jmp;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_plus_i:
|
|
Packit |
575503 |
case Op_minus_i:
|
|
Packit |
575503 |
case Op_times_i:
|
|
Packit |
575503 |
case Op_exp_i:
|
|
Packit |
575503 |
case Op_quotient_i:
|
|
Packit |
575503 |
case Op_mod_i:
|
|
Packit |
575503 |
m = pc->memory;
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (prec_level(pc->opcode) > prec_level(t1->type)
|
|
Packit |
575503 |
&& is_binary(t1->type)) /* (a - b) * 1 */
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
if ((m->flags & NUMBER) != 0)
|
|
Packit |
575503 |
tmp = pp_number(m);
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
tmp = pp_string(m->stptr, m->stlen, '"');
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, op2str(pc->opcode), tmp);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_parens:
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
str = pp_group3("(", t1->pp_str, ")");
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_plus:
|
|
Packit |
575503 |
case Op_minus:
|
|
Packit |
575503 |
case Op_times:
|
|
Packit |
575503 |
case Op_exp:
|
|
Packit |
575503 |
case Op_quotient:
|
|
Packit |
575503 |
case Op_mod:
|
|
Packit |
575503 |
case Op_equal:
|
|
Packit |
575503 |
case Op_notequal:
|
|
Packit |
575503 |
case Op_less:
|
|
Packit |
575503 |
case Op_greater:
|
|
Packit |
575503 |
case Op_leq:
|
|
Packit |
575503 |
case Op_geq:
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
parenthesize(pc->opcode, t1, t2);
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_preincrement:
|
|
Packit |
575503 |
case Op_predecrement:
|
|
Packit |
575503 |
case Op_postincrement:
|
|
Packit |
575503 |
case Op_postdecrement:
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (pc->opcode == Op_preincrement || pc->opcode == Op_predecrement)
|
|
Packit |
575503 |
str = pp_group3(op2str(pc->opcode), t1->pp_str, "");
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, op2str(pc->opcode), "");
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_field_spec:
|
|
Packit |
575503 |
case Op_field_spec_lhs:
|
|
Packit |
575503 |
case Op_unary_minus:
|
|
Packit |
575503 |
case Op_unary_plus:
|
|
Packit |
575503 |
case Op_not:
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t1->type)
|
|
Packit |
575503 |
|| (((OPCODE) t1->type) == pc->opcode
|
|
Packit |
575503 |
&& (pc->opcode == Op_unary_minus
|
|
Packit |
575503 |
|| pc->opcode == Op_unary_plus)))
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* optypes table (eval.c) includes space after ! */
|
|
Packit |
575503 |
str = pp_group3(op2str(pc->opcode), t1->pp_str, "");
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_assign:
|
|
Packit |
575503 |
case Op_assign_plus:
|
|
Packit |
575503 |
case Op_assign_minus:
|
|
Packit |
575503 |
case Op_assign_times:
|
|
Packit |
575503 |
case Op_assign_quotient:
|
|
Packit |
575503 |
case Op_assign_mod:
|
|
Packit |
575503 |
case Op_assign_exp:
|
|
Packit |
575503 |
t2 = pp_pop(); /* l.h.s. */
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
str = pp_group3(t2->pp_str, op2str(pc->opcode), t1->pp_str);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_store_field:
|
|
Packit |
575503 |
t1 = pp_pop(); /* field num */
|
|
Packit |
575503 |
if (is_binary(t1->type))
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
t2 = pp_pop(); /* r.h.s. */
|
|
Packit |
575503 |
fprintf(prof_fp, "$%s%s%s", t1->pp_str, op2str(pc->opcode), t2->pp_str);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
if ((flags & IN_FOR_HEADER) == 0)
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_concat:
|
|
Packit |
575503 |
str = pp_concat(pc->expr_count);
|
|
Packit |
575503 |
pp_push(Op_concat, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_delete:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *array;
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
array = t1->pp_str;
|
|
Packit |
575503 |
if (pc->expr_count > 0) {
|
|
Packit |
575503 |
char *sub;
|
|
Packit |
575503 |
sub = pp_list(pc->expr_count, NULL, pc->expr_count > 1 ? "][" : ", ");
|
|
Packit |
575503 |
fprintf(prof_fp, "%s %s[%s]", op2str(Op_K_delete), array, sub);
|
|
Packit |
575503 |
efree(sub);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array);
|
|
Packit |
575503 |
if ((flags & IN_FOR_HEADER) == 0)
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_delete_loop:
|
|
Packit |
575503 |
/* Efficency hack not in effect because of exec_count instruction */
|
|
Packit |
575503 |
cant_happen();
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_in_array:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *array, *sub;
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
array = t1->pp_str;
|
|
Packit |
575503 |
if (pc->expr_count > 1) {
|
|
Packit |
575503 |
sub = pp_list(pc->expr_count, "()", ", ");
|
|
Packit |
575503 |
str = pp_group3(sub, op2str(Op_in_array), array);
|
|
Packit |
575503 |
efree(sub);
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
if (prec_level(t2->type) < prec_level(Op_in_array)) {
|
|
Packit |
575503 |
pp_parenthesize(t2);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
sub = t2->pp_str;
|
|
Packit |
575503 |
str = pp_group3(sub, op2str(Op_in_array), array);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(Op_in_array, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_var_update:
|
|
Packit |
575503 |
case Op_var_assign:
|
|
Packit |
575503 |
case Op_field_assign:
|
|
Packit |
575503 |
case Op_subscript_assign:
|
|
Packit |
575503 |
case Op_arrayfor_init:
|
|
Packit |
575503 |
case Op_arrayfor_incr:
|
|
Packit |
575503 |
case Op_arrayfor_final:
|
|
Packit |
575503 |
case Op_newfile:
|
|
Packit |
575503 |
case Op_get_record:
|
|
Packit |
575503 |
case Op_lint:
|
|
Packit |
575503 |
case Op_jmp:
|
|
Packit |
575503 |
case Op_jmp_false:
|
|
Packit |
575503 |
case Op_jmp_true:
|
|
Packit |
575503 |
case Op_no_op:
|
|
Packit |
575503 |
case Op_and_final:
|
|
Packit |
575503 |
case Op_or_final:
|
|
Packit |
575503 |
case Op_cond_pair:
|
|
Packit |
575503 |
case Op_after_beginfile:
|
|
Packit |
575503 |
case Op_after_endfile:
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_sub_builtin:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
const char *fname = "sub";
|
|
Packit |
575503 |
if ((pc->sub_flags & GSUB) != 0)
|
|
Packit |
575503 |
fname = "gsub";
|
|
Packit |
575503 |
else if ((pc->sub_flags & GENSUB) != 0)
|
|
Packit |
575503 |
fname = "gensub";
|
|
Packit |
575503 |
tmp = pp_list(pc->expr_count, "()", ", ");
|
|
Packit |
575503 |
str = pp_group3(fname, tmp, "");
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
pp_push(Op_sub_builtin, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_builtin:
|
|
Packit |
575503 |
case Op_ext_builtin:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
const char *fname;
|
|
Packit |
575503 |
if (pc->opcode == Op_builtin)
|
|
Packit |
575503 |
fname = getfname(pc->builtin);
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
fname = (pc + 1)->func_name;
|
|
Packit |
575503 |
if (fname != NULL) {
|
|
Packit |
575503 |
if (pc->expr_count > 0) {
|
|
Packit |
575503 |
tmp = pp_list(pc->expr_count, "()", ", ");
|
|
Packit |
575503 |
str = pp_group3(fname, tmp, "");
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
str = pp_group3(fname, "()", "");
|
|
Packit |
575503 |
pp_push(Op_builtin, str, CAN_FREE);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
fatal(_("internal error: builtin with null fname"));
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_print:
|
|
Packit |
575503 |
case Op_K_printf:
|
|
Packit |
575503 |
case Op_K_print_rec:
|
|
Packit |
575503 |
if (pc->opcode == Op_K_print_rec)
|
|
Packit |
575503 |
tmp = pp_group3(" ", op2str(Op_field_spec), "0");
|
|
Packit |
575503 |
else if (pc->redir_type != 0)
|
|
Packit |
575503 |
tmp = pp_list(pc->expr_count, "()", ", ");
|
|
Packit |
575503 |
else {
|
|
Packit |
575503 |
tmp = pp_list(pc->expr_count, " ", ", ");
|
|
Packit |
575503 |
tmp[strlen(tmp) - 1] = '\0'; /* remove trailing space */
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pc->redir_type != 0) {
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t1->type))
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s%s%s%s", op2str(pc->opcode),
|
|
Packit |
575503 |
tmp, redir2str(pc->redir_type), t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
if ((flags & IN_FOR_HEADER) == 0)
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_push_re:
|
|
Packit |
575503 |
if (pc->memory->type != Node_regex && (pc->memory->flags & REGEX) == 0)
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
/* else
|
|
Packit |
575503 |
fall through */
|
|
Packit |
575503 |
case Op_match_rec:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
if (pc->memory->type == Node_regex) {
|
|
Packit |
575503 |
NODE *re = pc->memory->re_exp;
|
|
Packit |
575503 |
str = pp_string(re->stptr, re->stlen, '/');
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
assert((pc->memory->flags & REGEX) != 0);
|
|
Packit |
575503 |
str = pp_typed_regex(pc->memory->stptr, pc->memory->stlen, '/');
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_nomatch:
|
|
Packit |
575503 |
case Op_match:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *restr, *txt;
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t1->type))
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
txt = t1->pp_str;
|
|
Packit |
575503 |
m = pc->memory;
|
|
Packit |
575503 |
if (m->type == Node_dynregex) {
|
|
Packit |
575503 |
restr = txt;
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t2->type))
|
|
Packit |
575503 |
pp_parenthesize(t2);
|
|
Packit |
575503 |
txt = t2->pp_str;
|
|
Packit |
575503 |
str = pp_group3(txt, op2str(pc->opcode), restr);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
} else if (m->type == Node_val && (m->flags & REGEX) != 0) {
|
|
Packit |
575503 |
restr = pp_typed_regex(m->stptr, m->stlen, '/');
|
|
Packit |
575503 |
str = pp_group3(txt, op2str(pc->opcode), restr);
|
|
Packit |
575503 |
efree(restr);
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
NODE *re = m->re_exp;
|
|
Packit |
575503 |
restr = pp_string(re->stptr, re->stlen, '/');
|
|
Packit |
575503 |
str = pp_group3(txt, op2str(pc->opcode), restr);
|
|
Packit |
575503 |
efree(restr);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_getline:
|
|
Packit |
575503 |
case Op_K_getline_redir:
|
|
Packit |
575503 |
if (pc->into_var) {
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
tmp = pp_group3(op2str(Op_K_getline), " ", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
tmp = pp_group3(op2str(Op_K_getline), "", "");
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pc->redir_type != 0) {
|
|
Packit |
575503 |
int before = (pc->redir_type == redirect_pipein
|
|
Packit |
575503 |
|| pc->redir_type == redirect_twoway);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t2->type))
|
|
Packit |
575503 |
pp_parenthesize(t2);
|
|
Packit |
575503 |
if (before)
|
|
Packit |
575503 |
str = pp_group3(t2->pp_str, redir2str(pc->redir_type), tmp);
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
str = pp_group3(tmp, redir2str(pc->redir_type), t2->pp_str);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
str = tmp;
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_indirect_func_call:
|
|
Packit |
575503 |
case Op_func_call:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *fname = pc->func_name;
|
|
Packit |
575503 |
char *pre;
|
|
Packit |
575503 |
int pcount;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pc->opcode == Op_indirect_func_call)
|
|
Packit |
575503 |
pre = "@";
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
pre = "";
|
|
Packit |
575503 |
pcount = (pc + 1)->expr_count;
|
|
Packit |
575503 |
if (pcount > 0) {
|
|
Packit |
575503 |
tmp = pp_list(pcount, "()", ", ");
|
|
Packit |
575503 |
str = pp_group3(pre, fname, tmp);
|
|
Packit |
575503 |
efree(tmp);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
str = pp_group3(pre, fname, "()");
|
|
Packit |
575503 |
if (pc->opcode == Op_indirect_func_call) {
|
|
Packit |
575503 |
t1 = pp_pop(); /* indirect var */
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_push(pc->opcode, str, CAN_FREE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_continue:
|
|
Packit |
575503 |
case Op_K_break:
|
|
Packit |
575503 |
case Op_K_nextfile:
|
|
Packit |
575503 |
case Op_K_next:
|
|
Packit |
575503 |
fprintf(prof_fp, "%s", op2str(pc->opcode));
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_return:
|
|
Packit |
575503 |
case Op_K_exit:
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
if (is_binary(t1->type))
|
|
Packit |
575503 |
pp_parenthesize(t1);
|
|
Packit |
575503 |
if (pc->source_line > 0) { /* don't print implicit 'return' at end of function */
|
|
Packit |
575503 |
fprintf(prof_fp, "%s %s", op2str(pc->opcode), t1->pp_str);
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_pop:
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s", t1->pp_str);
|
|
Packit |
575503 |
if ((flags & IN_FOR_HEADER) == 0)
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_line_range:
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
pprint(pc->nexti, ip1->condpair_left, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
pprint(ip1->condpair_left->nexti, ip1->condpair_right, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
t2 = pp_pop();
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
str = pp_group3(t1->pp_str, ", ", t2->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pp_free(t2);
|
|
Packit |
575503 |
pp_push(Op_line_range, str, CAN_FREE);
|
|
Packit |
575503 |
pc = ip1->condpair_right;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_while:
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
indent(ip1->while_body->exec_count);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s (", op2str(pc->opcode));
|
|
Packit |
575503 |
pprint(pc->nexti, ip1->while_body, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s) {", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
ip1->while_body = end_line(ip1->while_body);
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(ip1->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}");
|
|
Packit |
575503 |
pc = end_line(pc->target_break);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_do:
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
indent(pc->nexti->exec_count);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s {", op2str(pc->opcode));
|
|
Packit |
575503 |
end_line(pc->nexti);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(pc->nexti->nexti, ip1->doloop_cond, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
pprint(ip1->doloop_cond, pc->target_break, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "} %s (%s)", op2str(Op_K_while), t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
end_line(pc->target_break);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
pc = pc->target_break;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_for:
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
indent(ip1->forloop_body->exec_count);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s (", op2str(pc->opcode));
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* If empty for looop header, print it a little more nicely. */
|
|
Packit |
575503 |
if ( pc->nexti->opcode == Op_no_op
|
|
Packit |
575503 |
&& ip1->forloop_cond == pc->nexti
|
|
Packit |
575503 |
&& pc->target_continue->opcode == Op_jmp) {
|
|
Packit |
575503 |
fprintf(prof_fp, ";;");
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
pprint(pc->nexti, ip1->forloop_cond, IN_FOR_HEADER);
|
|
Packit |
575503 |
fprintf(prof_fp, "; ");
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (ip1->forloop_cond->opcode == Op_no_op &&
|
|
Packit |
575503 |
ip1->forloop_cond->nexti == ip1->forloop_body)
|
|
Packit |
575503 |
fprintf(prof_fp, "; ");
|
|
Packit |
575503 |
else {
|
|
Packit |
575503 |
pprint(ip1->forloop_cond, ip1->forloop_body, IN_FOR_HEADER);
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s; ", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
pprint(pc->target_continue, pc->target_break, IN_FOR_HEADER);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
fprintf(prof_fp, ") {");
|
|
Packit |
575503 |
end_line(ip1->forloop_body);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(ip1->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}");
|
|
Packit |
575503 |
end_line(pc->target_break);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
pc = pc->target_break;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_arrayfor:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *array;
|
|
Packit |
575503 |
const char *item;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
array = t1->pp_str;
|
|
Packit |
575503 |
m = ip1->forloop_cond->array_var;
|
|
Packit |
575503 |
if (m->type == Node_param_list)
|
|
Packit |
575503 |
item = func_params[m->param_cnt].param;
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
item = m->vname;
|
|
Packit |
575503 |
indent(ip1->forloop_body->exec_count);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s (%s%s%s) {", op2str(Op_K_arrayfor),
|
|
Packit |
575503 |
item, op2str(Op_in_array), array);
|
|
Packit |
575503 |
end_line(ip1->forloop_body);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pprint(ip1->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}");
|
|
Packit |
575503 |
end_line(pc->target_break);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
pc = pc->target_break;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_switch:
|
|
Packit |
575503 |
ip1 = pc + 1;
|
|
Packit |
575503 |
fprintf(prof_fp, "%s (", op2str(pc->opcode));
|
|
Packit |
575503 |
pprint(pc->nexti, ip1->switch_start, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s) {\n", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
pprint(ip1->switch_start, ip1->switch_end, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}\n");
|
|
Packit |
575503 |
pc = pc->target_break;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_case:
|
|
Packit |
575503 |
case Op_K_default:
|
|
Packit |
575503 |
indent(pc->stmt_start->exec_count);
|
|
Packit |
575503 |
if (pc->opcode == Op_K_case) {
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s %s:", op2str(pc->opcode), t1->pp_str);
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
fprintf(prof_fp, "%s:", op2str(pc->opcode));
|
|
Packit |
575503 |
pc = end_line(pc);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_if:
|
|
Packit |
575503 |
fprintf(prof_fp, "%s (", op2str(pc->opcode));
|
|
Packit |
575503 |
pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
t1 = pp_pop();
|
|
Packit |
575503 |
fprintf(prof_fp, "%s) {", t1->pp_str);
|
|
Packit |
575503 |
pp_free(t1);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
ip1 = pc->branch_if;
|
|
Packit |
575503 |
if (ip1->exec_count > 0)
|
|
Packit |
575503 |
fprintf(prof_fp, " # %ld", ip1->exec_count);
|
|
Packit |
575503 |
ip1 = end_line(ip1);
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
pc = pc->branch_else;
|
|
Packit |
575503 |
if (pc->nexti->opcode == Op_no_op) { /* no following else */
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}");
|
|
Packit |
575503 |
if (pc->nexti->nexti->opcode != Op_comment
|
|
Packit |
575503 |
|| pc->nexti->nexti->memory->comment_type == FULL_COMMENT)
|
|
Packit |
575503 |
fprintf(prof_fp, "\n");
|
|
Packit |
575503 |
/* else
|
|
Packit |
575503 |
It will be printed at the top. */
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* See next case; turn off the flag so that the
|
|
Packit |
575503 |
* following else is correctly indented.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
flags &= ~IN_ELSE_IF;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_else:
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* If possible, chain else-if's together on the
|
|
Packit |
575503 |
* same line.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* See awkgram.y:mk_condition to understand
|
|
Packit |
575503 |
* what is being checked here.
|
|
Packit |
575503 |
*
|
|
Packit |
575503 |
* Op_exec_count follows Op_K_else, check the
|
|
Packit |
575503 |
* opcode of the following instruction.
|
|
Packit |
575503 |
* Additionally, check that the subsequent if
|
|
Packit |
575503 |
* terminates where this else does; in that case
|
|
Packit |
575503 |
* it's ok to compact the if to follow the else.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
fprintf(prof_fp, "} %s ", op2str(pc->opcode));
|
|
Packit |
575503 |
if (pc->nexti->nexti->opcode == Op_K_if
|
|
Packit |
575503 |
&& pc->branch_end == pc->nexti->nexti->branch_else->lasti) {
|
|
Packit |
575503 |
pprint(pc->nexti, pc->branch_end, IN_ELSE_IF);
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
fprintf(prof_fp, "{");
|
|
Packit |
575503 |
end_line(pc);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
indent(SPACEOVER);
|
|
Packit |
575503 |
fprintf(prof_fp, "}");
|
|
Packit |
575503 |
end_line(pc->branch_end);
|
|
Packit |
575503 |
skip_comment = true;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* Don't do end_line() here, we get multiple blank lines after
|
|
Packit |
575503 |
* the final else in a chain of else-ifs since they all point
|
|
Packit |
575503 |
* to the same branch_end.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
pc = pc->branch_end;
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_cond_exp:
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
NODE *f, *t, *cond;
|
|
Packit |
575503 |
size_t len;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
ip1 = pc->branch_if;
|
|
Packit |
575503 |
pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
ip1 = pc->branch_else->nexti;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
pc = ip1->nexti;
|
|
Packit |
575503 |
assert(pc->opcode == Op_cond_exp);
|
|
Packit |
575503 |
pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
f = pp_pop();
|
|
Packit |
575503 |
t = pp_pop();
|
|
Packit |
575503 |
cond = pp_pop();
|
|
Packit |
575503 |
|
|
Packit |
575503 |
len = f->pp_len + t->pp_len + cond->pp_len + 12;
|
|
Packit |
575503 |
emalloc(str, char *, len, "pprint");
|
|
Packit |
575503 |
sprintf(str, "%s ? %s : %s", cond->pp_str, t->pp_str, f->pp_str);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
pp_free(cond);
|
|
Packit |
575503 |
pp_free(t);
|
|
Packit |
575503 |
pp_free(f);
|
|
Packit |
575503 |
pp_push(Op_cond_exp, str, CAN_FREE);
|
|
Packit |
575503 |
pc = pc->branch_end;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_exec_count:
|
|
Packit |
575503 |
if (flags == NO_PPRINT_FLAGS)
|
|
Packit |
575503 |
indent(pc->exec_count);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_comment:
|
|
Packit |
575503 |
print_comment(pc, 0);
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_list:
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
cant_happen();
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pc == endp)
|
|
Packit |
575503 |
break;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* end_line --- end pretty print line with new line or on-line comment */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
INSTRUCTION *
|
|
Packit |
575503 |
end_line(INSTRUCTION *ip)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
INSTRUCTION *ret = ip;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (ip->nexti->opcode == Op_comment
|
|
Packit |
575503 |
&& ip->nexti->memory->comment_type == EOL_COMMENT) {
|
|
Packit |
575503 |
fprintf(prof_fp, "\t");
|
|
Packit |
575503 |
print_comment(ip->nexti, -1);
|
|
Packit |
575503 |
ret = ip->nexti;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
else
|
|
Packit |
575503 |
fprintf(prof_fp, "\n");
|
|
Packit |
575503 |
|
|
Packit |
575503 |
return ret;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_string_fp --- printy print a string to the fp */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* This routine concentrates string pretty printing in one place,
|
|
Packit |
575503 |
* so that it can be called from multiple places within gawk.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
void
|
|
Packit |
575503 |
pp_string_fp(Func_print print_func, FILE *fp, const char *in_str,
|
|
Packit |
575503 |
size_t len, int delim, bool breaklines)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *s = pp_string(in_str, len, delim);
|
|
Packit |
575503 |
int count;
|
|
Packit |
575503 |
size_t slen;
|
|
Packit |
575503 |
const char *str = (const char *) s;
|
|
Packit |
575503 |
#define BREAKPOINT 70 /* arbitrary */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
slen = strlen(str);
|
|
Packit |
575503 |
for (count = 0; slen > 0; slen--, str++) {
|
|
Packit |
575503 |
print_func(fp, "%c", *str);
|
|
Packit |
575503 |
if (++count >= BREAKPOINT && breaklines) {
|
|
Packit |
575503 |
print_func(fp, "%c\n%c", delim, delim);
|
|
Packit |
575503 |
count = 0;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
efree(s);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* just_dump --- dump the profile and function stack and keep going */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
just_dump(int signum)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
extern INSTRUCTION *code_block;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
dump_prog(code_block);
|
|
Packit |
575503 |
dump_funcs();
|
|
Packit |
575503 |
dump_fcall_stack(prof_fp);
|
|
Packit |
575503 |
fflush(prof_fp);
|
|
Packit |
575503 |
signal(signum, just_dump); /* for OLD Unix systems ... */
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* dump_and_exit --- dump the profile, the function stack, and exit */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
dump_and_exit(int signum)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
just_dump(signum);
|
|
Packit |
575503 |
final_exit(EXIT_FAILURE);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* print_lib_list --- print a list of all libraries loaded */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
print_lib_list(FILE *prof_fp)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
SRCFILE *s;
|
|
Packit |
575503 |
static bool printed_header = false;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
for (s = srcfiles->next; s != srcfiles; s = s->next) {
|
|
Packit |
575503 |
if (s->stype == SRC_EXTLIB) {
|
|
Packit |
575503 |
if (! printed_header) {
|
|
Packit |
575503 |
printed_header = true;
|
|
Packit |
575503 |
fprintf(prof_fp, _("\t# Loaded extensions (-l and/or @load)\n\n"));
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
fprintf(prof_fp, "\t@load \"%s\"\n", s->src);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (printed_header) /* we found some */
|
|
Packit |
575503 |
fprintf(prof_fp, "\n");
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* print_comment --- print comment text with proper indentation */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
print_comment(INSTRUCTION* pc, long in)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *text;
|
|
Packit |
575503 |
size_t count;
|
|
Packit |
575503 |
bool after_newline = false;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
count = pc->memory->stlen;
|
|
Packit |
575503 |
text = pc->memory->stptr;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (in >= 0)
|
|
Packit |
575503 |
indent(in); /* is this correct? Where should comments go? */
|
|
Packit |
575503 |
for (; count > 0; count--, text++) {
|
|
Packit |
575503 |
if (after_newline) {
|
|
Packit |
575503 |
indent(in);
|
|
Packit |
575503 |
after_newline = false;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
putc(*text, prof_fp);
|
|
Packit |
575503 |
if (*text == '\n')
|
|
Packit |
575503 |
after_newline = true;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* dump_prog --- dump the program */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* XXX: I am not sure it is right to have the strings in the dump
|
|
Packit |
575503 |
* be translated, but I'll leave it alone for now.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
void
|
|
Packit |
575503 |
dump_prog(INSTRUCTION *code)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
time_t now;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
(void) time(& now);
|
|
Packit |
575503 |
/* \n on purpose, with \n in ctime() output */
|
|
Packit |
575503 |
if (do_profile)
|
|
Packit |
575503 |
fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
|
|
Packit |
575503 |
print_lib_list(prof_fp);
|
|
Packit |
575503 |
pprint(code, NULL, NO_PPRINT_FLAGS);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* prec_level --- return the precedence of an operator, for paren tests */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static int
|
|
Packit |
575503 |
prec_level(int type)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
switch (type) {
|
|
Packit |
575503 |
case Op_push_lhs:
|
|
Packit |
575503 |
case Op_push_param:
|
|
Packit |
575503 |
case Op_push_array:
|
|
Packit |
575503 |
case Op_push:
|
|
Packit |
575503 |
case Op_push_i:
|
|
Packit |
575503 |
case Op_push_re:
|
|
Packit |
575503 |
case Op_match_rec:
|
|
Packit |
575503 |
case Op_subscript:
|
|
Packit |
575503 |
case Op_subscript_lhs:
|
|
Packit |
575503 |
case Op_func_call:
|
|
Packit |
575503 |
case Op_K_delete_loop:
|
|
Packit |
575503 |
case Op_builtin:
|
|
Packit |
575503 |
return 16;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_field_spec:
|
|
Packit |
575503 |
case Op_field_spec_lhs:
|
|
Packit |
575503 |
return 15;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_preincrement:
|
|
Packit |
575503 |
case Op_predecrement:
|
|
Packit |
575503 |
case Op_postincrement:
|
|
Packit |
575503 |
case Op_postdecrement:
|
|
Packit |
575503 |
return 14;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_exp:
|
|
Packit |
575503 |
case Op_exp_i:
|
|
Packit |
575503 |
return 13;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_unary_minus:
|
|
Packit |
575503 |
case Op_unary_plus:
|
|
Packit |
575503 |
case Op_not:
|
|
Packit |
575503 |
return 12;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_times:
|
|
Packit |
575503 |
case Op_times_i:
|
|
Packit |
575503 |
case Op_quotient:
|
|
Packit |
575503 |
case Op_quotient_i:
|
|
Packit |
575503 |
case Op_mod:
|
|
Packit |
575503 |
case Op_mod_i:
|
|
Packit |
575503 |
return 11;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_plus:
|
|
Packit |
575503 |
case Op_plus_i:
|
|
Packit |
575503 |
case Op_minus:
|
|
Packit |
575503 |
case Op_minus_i:
|
|
Packit |
575503 |
return 10;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_concat:
|
|
Packit |
575503 |
case Op_assign_concat:
|
|
Packit |
575503 |
return 9;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_equal:
|
|
Packit |
575503 |
case Op_notequal:
|
|
Packit |
575503 |
case Op_greater:
|
|
Packit |
575503 |
case Op_less:
|
|
Packit |
575503 |
case Op_leq:
|
|
Packit |
575503 |
case Op_geq:
|
|
Packit |
575503 |
return 8;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_match:
|
|
Packit |
575503 |
case Op_nomatch:
|
|
Packit |
575503 |
return 7;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_K_getline:
|
|
Packit |
575503 |
case Op_K_getline_redir:
|
|
Packit |
575503 |
return 6;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_in_array:
|
|
Packit |
575503 |
return 5;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_and:
|
|
Packit |
575503 |
return 4;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_or:
|
|
Packit |
575503 |
return 3;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_cond_exp:
|
|
Packit |
575503 |
return 2;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
case Op_assign:
|
|
Packit |
575503 |
case Op_assign_times:
|
|
Packit |
575503 |
case Op_assign_quotient:
|
|
Packit |
575503 |
case Op_assign_mod:
|
|
Packit |
575503 |
case Op_assign_plus:
|
|
Packit |
575503 |
case Op_assign_minus:
|
|
Packit |
575503 |
case Op_assign_exp:
|
|
Packit |
575503 |
return 1;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
return 0;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* is_scalar --- return true if scalar, false otherwise */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static bool
|
|
Packit |
575503 |
is_scalar(int type)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
switch (type) {
|
|
Packit |
575503 |
case Op_push_lhs:
|
|
Packit |
575503 |
case Op_push_param:
|
|
Packit |
575503 |
case Op_push_array:
|
|
Packit |
575503 |
case Op_push:
|
|
Packit |
575503 |
case Op_push_i:
|
|
Packit |
575503 |
case Op_push_re:
|
|
Packit |
575503 |
case Op_subscript:
|
|
Packit |
575503 |
case Op_subscript_lhs:
|
|
Packit |
575503 |
case Op_func_call:
|
|
Packit |
575503 |
case Op_builtin:
|
|
Packit |
575503 |
case Op_field_spec:
|
|
Packit |
575503 |
case Op_field_spec_lhs:
|
|
Packit |
575503 |
case Op_preincrement:
|
|
Packit |
575503 |
case Op_predecrement:
|
|
Packit |
575503 |
case Op_postincrement:
|
|
Packit |
575503 |
case Op_postdecrement:
|
|
Packit |
575503 |
case Op_unary_minus:
|
|
Packit |
575503 |
case Op_unary_plus:
|
|
Packit |
575503 |
case Op_not:
|
|
Packit |
575503 |
return true;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
return false;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* is_binary --- return true if type represents a binary operator */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static bool
|
|
Packit |
575503 |
is_binary(int type)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
switch (type) {
|
|
Packit |
575503 |
case Op_geq:
|
|
Packit |
575503 |
case Op_leq:
|
|
Packit |
575503 |
case Op_greater:
|
|
Packit |
575503 |
case Op_less:
|
|
Packit |
575503 |
case Op_notequal:
|
|
Packit |
575503 |
case Op_equal:
|
|
Packit |
575503 |
case Op_exp:
|
|
Packit |
575503 |
case Op_times:
|
|
Packit |
575503 |
case Op_quotient:
|
|
Packit |
575503 |
case Op_mod:
|
|
Packit |
575503 |
case Op_plus:
|
|
Packit |
575503 |
case Op_minus:
|
|
Packit |
575503 |
case Op_exp_i:
|
|
Packit |
575503 |
case Op_times_i:
|
|
Packit |
575503 |
case Op_quotient_i:
|
|
Packit |
575503 |
case Op_mod_i:
|
|
Packit |
575503 |
case Op_plus_i:
|
|
Packit |
575503 |
case Op_minus_i:
|
|
Packit |
575503 |
case Op_concat:
|
|
Packit |
575503 |
case Op_assign_concat:
|
|
Packit |
575503 |
case Op_match:
|
|
Packit |
575503 |
case Op_nomatch:
|
|
Packit |
575503 |
case Op_assign:
|
|
Packit |
575503 |
case Op_assign_times:
|
|
Packit |
575503 |
case Op_assign_quotient:
|
|
Packit |
575503 |
case Op_assign_mod:
|
|
Packit |
575503 |
case Op_assign_plus:
|
|
Packit |
575503 |
case Op_assign_minus:
|
|
Packit |
575503 |
case Op_assign_exp:
|
|
Packit |
575503 |
case Op_cond_exp:
|
|
Packit |
575503 |
case Op_and:
|
|
Packit |
575503 |
case Op_or:
|
|
Packit |
575503 |
case Op_in_array:
|
|
Packit |
575503 |
case Op_K_getline_redir: /* sometimes */
|
|
Packit |
575503 |
case Op_K_getline:
|
|
Packit |
575503 |
return true;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
default:
|
|
Packit |
575503 |
return false;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_parenthesize --- parenthesize an expression in stack */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
pp_parenthesize(NODE *sp)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *p = sp->pp_str;
|
|
Packit |
575503 |
size_t len = sp->pp_len;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (p[0] == '(') // already parenthesized
|
|
Packit |
575503 |
return;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
emalloc(p, char *, len + 3, "pp_parenthesize");
|
|
Packit |
575503 |
*p = '(';
|
|
Packit |
575503 |
memcpy(p + 1, sp->pp_str, len);
|
|
Packit |
575503 |
p[len + 1] = ')';
|
|
Packit |
575503 |
p[len + 2] = '\0';
|
|
Packit |
575503 |
if ((sp->flags & CAN_FREE) != 0)
|
|
Packit |
575503 |
efree(sp->pp_str);
|
|
Packit |
575503 |
sp->pp_str = p;
|
|
Packit |
575503 |
sp->pp_len += 2;
|
|
Packit |
575503 |
sp->flags |= CAN_FREE;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* parenthesize --- parenthesize two nodes relative to parent node type */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static void
|
|
Packit |
575503 |
parenthesize(int type, NODE *left, NODE *right)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
int rprec = prec_level(right->type);
|
|
Packit |
575503 |
int lprec = prec_level(left->type);
|
|
Packit |
575503 |
int prec = prec_level(type);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (lprec < prec)
|
|
Packit |
575503 |
pp_parenthesize(left);
|
|
Packit |
575503 |
if (rprec < prec)
|
|
Packit |
575503 |
pp_parenthesize(right);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_string --- pretty format a string or regular regex constant */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
char *
|
|
Packit |
575503 |
pp_string(const char *in_str, size_t len, int delim)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
return pp_string_or_typed_regex(in_str, len, delim, false);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_typed_regex --- pretty format a hard regex constant */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static char *
|
|
Packit |
575503 |
pp_typed_regex(const char *in_str, size_t len, int delim)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
return pp_string_or_typed_regex(in_str, len, delim, true);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_string_or_typed_regex --- pretty format a string, regex, or typed regex constant */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
char *
|
|
Packit |
575503 |
pp_string_or_typed_regex(const char *in_str, size_t len, int delim, bool typed_regex)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
static char str_escapes[] = "\a\b\f\n\r\t\v\\";
|
|
Packit |
575503 |
static char str_printables[] = "abfnrtv\\";
|
|
Packit |
575503 |
static char re_escapes[] = "\a\b\f\n\r\t\v";
|
|
Packit |
575503 |
static char re_printables[] = "abfnrtv";
|
|
Packit |
575503 |
char *escapes;
|
|
Packit |
575503 |
char *printables;
|
|
Packit |
575503 |
char *cp;
|
|
Packit |
575503 |
int i;
|
|
Packit |
575503 |
const unsigned char *str = (const unsigned char *) in_str;
|
|
Packit |
575503 |
size_t ofre, osiz;
|
|
Packit |
575503 |
char *obuf, *obufout;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
assert(delim == '"' || delim == '/');
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (delim == '/') {
|
|
Packit |
575503 |
escapes = re_escapes;
|
|
Packit |
575503 |
printables = re_printables;
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
escapes = str_escapes;
|
|
Packit |
575503 |
printables = str_printables;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* make space for something l big in the buffer */
|
|
Packit |
575503 |
#define chksize(l) if ((l) > ofre) { \
|
|
Packit |
575503 |
long olen = obufout - obuf; \
|
|
Packit |
575503 |
erealloc(obuf, char *, osiz * 2, "pp_string"); \
|
|
Packit |
575503 |
obufout = obuf + olen; \
|
|
Packit |
575503 |
ofre += osiz; \
|
|
Packit |
575503 |
osiz *= 2; \
|
|
Packit |
575503 |
} ofre -= (l)
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* initial size; 3 for delim + terminating null, 1 for @ */
|
|
Packit |
575503 |
osiz = len + 3 + 1 + (typed_regex == true);
|
|
Packit |
575503 |
emalloc(obuf, char *, osiz, "pp_string");
|
|
Packit |
575503 |
obufout = obuf;
|
|
Packit |
575503 |
ofre = osiz - 1;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (typed_regex)
|
|
Packit |
575503 |
*obufout++ = '@';
|
|
Packit |
575503 |
|
|
Packit |
575503 |
*obufout++ = delim;
|
|
Packit |
575503 |
for (; len > 0; len--, str++) {
|
|
Packit |
575503 |
chksize(2); /* make space for 2 chars */
|
|
Packit |
575503 |
if (delim != '/' && *str == delim) {
|
|
Packit |
575503 |
*obufout++ = '\\';
|
|
Packit |
575503 |
*obufout++ = delim;
|
|
Packit |
575503 |
} else if (*str == '\0') {
|
|
Packit |
575503 |
*obufout++ = '\\';
|
|
Packit |
575503 |
*obufout++ = '0';
|
|
Packit |
575503 |
chksize(2); /* need 2 more chars for this case */
|
|
Packit |
575503 |
*obufout++ = '0';
|
|
Packit |
575503 |
*obufout++ = '0';
|
|
Packit |
575503 |
} else if ((cp = strchr(escapes, *str)) != NULL) {
|
|
Packit |
575503 |
i = cp - escapes;
|
|
Packit |
575503 |
*obufout++ = '\\';
|
|
Packit |
575503 |
*obufout++ = printables[i];
|
|
Packit |
575503 |
/* NB: Deliberate use of lower-case versions. */
|
|
Packit |
575503 |
} else if (isascii(*str) && isprint(*str)) {
|
|
Packit |
575503 |
*obufout++ = *str;
|
|
Packit |
575503 |
ofre += 1; /* used 1 less than expected */
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
size_t len;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
chksize(8); /* total available space is 10 */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
sprintf(obufout, "\\%03o", *str & 0xff);
|
|
Packit |
575503 |
len = strlen(obufout);
|
|
Packit |
575503 |
ofre += (10 - len); /* adjust free space count */
|
|
Packit |
575503 |
obufout += len;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
chksize(2);
|
|
Packit |
575503 |
*obufout++ = delim;
|
|
Packit |
575503 |
*obufout = '\0';
|
|
Packit |
575503 |
return obuf;
|
|
Packit |
575503 |
#undef chksize
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_number --- pretty format a number */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
char *
|
|
Packit |
575503 |
pp_number(NODE *n)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
char *str;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
assert((n->flags & NUMCONSTSTR) != 0);
|
|
Packit |
575503 |
emalloc(str, char *, n->stlen + 1, "pp_number");
|
|
Packit |
575503 |
strcpy(str, n->stptr);
|
|
Packit |
575503 |
return str;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_node --- pretty format a node */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
char *
|
|
Packit |
575503 |
pp_node(NODE *n)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
if ((n->flags & NUMBER) != 0)
|
|
Packit |
575503 |
return pp_number(n);
|
|
Packit |
575503 |
return pp_string(n->stptr, n->stlen, '"');
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_list --- pretty print a list, with surrounding characters and separator */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static NODE **pp_args = NULL;
|
|
Packit |
575503 |
static int npp_args;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static char *
|
|
Packit |
575503 |
pp_list(int nargs, const char *paren, const char *delim)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
NODE *r;
|
|
Packit |
575503 |
char *str, *s;
|
|
Packit |
575503 |
size_t len;
|
|
Packit |
575503 |
size_t delimlen;
|
|
Packit |
575503 |
int i;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pp_args == NULL) {
|
|
Packit |
575503 |
npp_args = nargs;
|
|
Packit |
575503 |
emalloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_list");
|
|
Packit |
575503 |
} else if (nargs > npp_args) {
|
|
Packit |
575503 |
npp_args = nargs;
|
|
Packit |
575503 |
erealloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_list");
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
delimlen = strlen(delim);
|
|
Packit |
575503 |
if (nargs == 0)
|
|
Packit |
575503 |
len = 2;
|
|
Packit |
575503 |
else {
|
|
Packit |
575503 |
len = -delimlen;
|
|
Packit |
575503 |
for (i = 1; i <= nargs; i++) {
|
|
Packit |
575503 |
r = pp_args[i] = pp_pop();
|
|
Packit |
575503 |
len += r->pp_len + delimlen;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (paren != NULL) {
|
|
Packit |
575503 |
assert(strlen(paren) == 2);
|
|
Packit |
575503 |
len += 2;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
emalloc(str, char *, len + 1, "pp_list");
|
|
Packit |
575503 |
s = str;
|
|
Packit |
575503 |
if (paren != NULL)
|
|
Packit |
575503 |
*s++ = paren[0];
|
|
Packit |
575503 |
if (nargs > 0) {
|
|
Packit |
575503 |
r = pp_args[nargs];
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
pp_free(r);
|
|
Packit |
575503 |
for (i = nargs - 1; i > 0; i--) {
|
|
Packit |
575503 |
if (delimlen > 0) {
|
|
Packit |
575503 |
memcpy(s, delim, delimlen);
|
|
Packit |
575503 |
s += delimlen;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
r = pp_args[i];
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
pp_free(r);
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (paren != NULL)
|
|
Packit |
575503 |
*s++ = paren[1];
|
|
Packit |
575503 |
*s = '\0';
|
|
Packit |
575503 |
return str;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* is_unary_minus --- return true if string starts with unary minus */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static bool
|
|
Packit |
575503 |
is_unary_minus(const char *str)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
return str[0] == '-' && str[1] != '-';
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_concat --- handle concatenation and correct parenthesizing of expressions */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static char *
|
|
Packit |
575503 |
pp_concat(int nargs)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
NODE *r;
|
|
Packit |
575503 |
char *str, *s;
|
|
Packit |
575503 |
size_t len;
|
|
Packit |
575503 |
static const size_t delimlen = 1; /* " " */
|
|
Packit |
575503 |
int i;
|
|
Packit |
575503 |
int pl_l, pl_r;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (pp_args == NULL) {
|
|
Packit |
575503 |
npp_args = nargs;
|
|
Packit |
575503 |
emalloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_concat");
|
|
Packit |
575503 |
} else if (nargs > npp_args) {
|
|
Packit |
575503 |
npp_args = nargs;
|
|
Packit |
575503 |
erealloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_concat");
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/*
|
|
Packit |
575503 |
* items are on the stack in reverse order that they
|
|
Packit |
575503 |
* will be printed to pop them off backwards.
|
|
Packit |
575503 |
*/
|
|
Packit |
575503 |
|
|
Packit |
575503 |
len = -delimlen;
|
|
Packit |
575503 |
for (i = nargs; i >= 1; i--) {
|
|
Packit |
575503 |
r = pp_args[i] = pp_pop();
|
|
Packit |
575503 |
len += r->pp_len + delimlen + 2;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
emalloc(str, char *, len + 1, "pp_concat");
|
|
Packit |
575503 |
s = str;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* now copy in */
|
|
Packit |
575503 |
for (i = 1; i < nargs; i++) {
|
|
Packit |
575503 |
r = pp_args[i];
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (r->pp_str[0] != '(') {
|
|
Packit |
575503 |
pl_l = prec_level(pp_args[i]->type);
|
|
Packit |
575503 |
pl_r = prec_level(pp_args[i+1]->type);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (i >= 2 && is_unary_minus(r->pp_str)) {
|
|
Packit |
575503 |
*s++ = '(';
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
*s++ = ')';
|
|
Packit |
575503 |
} else if (is_scalar(pp_args[i]->type) && is_scalar(pp_args[i+1]->type)) {
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
} else if (pl_l <= pl_r || is_scalar(pp_args[i+1]->type)) {
|
|
Packit |
575503 |
*s++ = '(';
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
*s++ = ')';
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_free(r);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (i < nargs) {
|
|
Packit |
575503 |
*s++ = ' ';
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
pl_l = prec_level(pp_args[nargs-1]->type);
|
|
Packit |
575503 |
pl_r = prec_level(pp_args[nargs]->type);
|
|
Packit |
575503 |
r = pp_args[nargs];
|
|
Packit |
575503 |
if (r->pp_str[0] == '(') {
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
} else if (is_unary_minus(r->pp_str) || ((pl_l >= pl_r && ! is_scalar(pp_args[nargs]->type)))) {
|
|
Packit |
575503 |
*s++ = '(';
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
*s++ = ')';
|
|
Packit |
575503 |
} else {
|
|
Packit |
575503 |
memcpy(s, r->pp_str, r->pp_len);
|
|
Packit |
575503 |
s += r->pp_len;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
pp_free(r);
|
|
Packit |
575503 |
|
|
Packit |
575503 |
*s = '\0';
|
|
Packit |
575503 |
return str;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_group3 --- string together up to 3 strings */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
static char *
|
|
Packit |
575503 |
pp_group3(const char *s1, const char *s2, const char *s3)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
size_t len1, len2, len3, l;
|
|
Packit |
575503 |
char *str, *s;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
len1 = strlen(s1);
|
|
Packit |
575503 |
len2 = strlen(s2);
|
|
Packit |
575503 |
len3 = strlen(s3);
|
|
Packit |
575503 |
l = len1 + len2 + len3 + 1;
|
|
Packit |
575503 |
emalloc(str, char *, l, "pp_group3");
|
|
Packit |
575503 |
s = str;
|
|
Packit |
575503 |
if (len1 > 0) {
|
|
Packit |
575503 |
memcpy(s, s1, len1);
|
|
Packit |
575503 |
s += len1;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (len2 > 0) {
|
|
Packit |
575503 |
memcpy(s, s2, len2);
|
|
Packit |
575503 |
s += len2;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (len3 > 0) {
|
|
Packit |
575503 |
memcpy(s, s3, len3);
|
|
Packit |
575503 |
s += len3;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
*s = '\0';
|
|
Packit |
575503 |
return str;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* pp_func --- pretty print a function */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
int
|
|
Packit |
575503 |
pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
int j;
|
|
Packit |
575503 |
static bool first = true;
|
|
Packit |
575503 |
NODE *func;
|
|
Packit |
575503 |
int pcount;
|
|
Packit |
575503 |
INSTRUCTION *fp;
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (first) {
|
|
Packit |
575503 |
first = false;
|
|
Packit |
575503 |
if (do_profile)
|
|
Packit |
575503 |
fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n"));
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
fp = pc->nexti->nexti;
|
|
Packit |
575503 |
func = pc->func_body;
|
|
Packit |
575503 |
fprintf(prof_fp, "\n");
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* print any function comment */
|
|
Packit |
575503 |
if (fp->opcode == Op_comment && fp->source_line == 0) {
|
|
Packit |
575503 |
print_comment(fp, -1); /* -1 ==> don't indent */
|
|
Packit |
575503 |
fp = fp->nexti;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
indent(pc->nexti->exec_count);
|
|
Packit |
575503 |
fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);
|
|
Packit |
575503 |
pcount = func->param_cnt;
|
|
Packit |
575503 |
func_params = func->fparms;
|
|
Packit |
575503 |
for (j = 0; j < pcount; j++) {
|
|
Packit |
575503 |
fprintf(prof_fp, "%s", func_params[j].param);
|
|
Packit |
575503 |
if (j < pcount - 1)
|
|
Packit |
575503 |
fprintf(prof_fp, ", ");
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
if (fp->opcode == Op_comment
|
|
Packit |
575503 |
&& fp->memory->comment_type == EOL_COMMENT) {
|
|
Packit |
575503 |
fprintf(prof_fp, ")");
|
|
Packit |
575503 |
fp = end_line(fp);
|
|
Packit |
575503 |
} else
|
|
Packit |
575503 |
fprintf(prof_fp, ")\n");
|
|
Packit |
575503 |
if (do_profile)
|
|
Packit |
575503 |
indent(0);
|
|
Packit |
575503 |
fprintf(prof_fp, "{\n");
|
|
Packit |
575503 |
indent_in();
|
|
Packit |
575503 |
pprint(fp, NULL, NO_PPRINT_FLAGS); /* function body */
|
|
Packit |
575503 |
indent_out();
|
|
Packit |
575503 |
if (do_profile)
|
|
Packit |
575503 |
indent(0);
|
|
Packit |
575503 |
fprintf(prof_fp, "}\n");
|
|
Packit |
575503 |
return 0;
|
|
Packit |
575503 |
}
|
|
Packit |
575503 |
|
|
Packit |
575503 |
/* redir2str --- convert a redirection type into a printable value */
|
|
Packit |
575503 |
|
|
Packit |
575503 |
const char *
|
|
Packit |
575503 |
redir2str(int redirtype)
|
|
Packit |
575503 |
{
|
|
Packit |
575503 |
static const char *const redirtab[] = {
|
|
Packit |
575503 |
"",
|
|
Packit |
575503 |
" > ", /* redirect_output */
|
|
Packit |
575503 |
" >> ", /* redirect_append */
|
|
Packit |
575503 |
" | ", /* redirect_pipe */
|
|
Packit |
575503 |
" | ", /* redirect_pipein */
|
|
Packit |
575503 |
" < ", /* redirect_input */
|
|
Packit |
575503 |
" |& ", /* redirect_twoway */
|
|
Packit |
575503 |
};
|
|
Packit |
575503 |
|
|
Packit |
575503 |
if (redirtype < 0 || redirtype > redirect_twoway)
|
|
Packit |
575503 |
fatal(_("redir2str: unknown redirection type %d"), redirtype);
|
|
Packit |
575503 |
return redirtab[redirtype];
|
|
Packit |
575503 |
}
|