Print this page
7085 add support for "if" and "else" statements in dtrace


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.

  24  * Copyright (c) 2013, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2013 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * DTrace D Language Parser
  30  *
  31  * The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the
  32  * parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles
  33  * the construction of the parse tree nodes and their syntactic validation.
  34  * The parse tree is constructed of dt_node_t structures (see <dt_parser.h>)
  35  * that are built in two passes: (1) the "create" pass, where the parse tree
  36  * nodes are allocated by calls from the grammar to dt_node_*() subroutines,
  37  * and (2) the "cook" pass, where nodes are coalesced, assigned D types, and
  38  * validated according to the syntactic rules of the language.
  39  *
  40  * All node allocations are performed using dt_node_alloc().  All node frees
  41  * during the parsing phase are performed by dt_node_free(), which frees node-
  42  * internal state but does not actually free the nodes.  All final node frees
  43  * are done as part of the end of dt_compile() or as part of destroying
  44  * persistent identifiers or translators which have embedded nodes.
  45  *


2120 
2121 dt_node_t *
2122 dt_node_statement(dt_node_t *expr)
2123 {
2124         dt_node_t *dnp;
2125 
2126         if (expr->dn_kind == DT_NODE_AGG)
2127                 return (expr);
2128 
2129         if (expr->dn_kind == DT_NODE_FUNC &&
2130             expr->dn_ident->di_kind == DT_IDENT_ACTFUNC)
2131                 dnp = dt_node_alloc(DT_NODE_DFUNC);
2132         else
2133                 dnp = dt_node_alloc(DT_NODE_DEXPR);
2134 
2135         dnp->dn_expr = expr;
2136         return (dnp);
2137 }
2138 
2139 dt_node_t *











2140 dt_node_pdesc_by_name(char *spec)
2141 {
2142         dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2143         dt_node_t *dnp;
2144 
2145         if (spec == NULL)
2146                 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2147 
2148         dnp = dt_node_alloc(DT_NODE_PDESC);
2149         dnp->dn_spec = spec;
2150         dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t));
2151 
2152         if (dnp->dn_desc == NULL)
2153                 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2154 
2155         if (dtrace_xstr2desc(dtp, yypcb->pcb_pspec, dnp->dn_spec,
2156             yypcb->pcb_sargc, yypcb->pcb_sargv, dnp->dn_desc) != 0) {
2157                 xyerror(D_PDESC_INVAL, "invalid probe description \"%s\": %s\n",
2158                     dnp->dn_spec, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2159         }


2188                     names[yypcb->pcb_pspec]);
2189         }
2190 
2191         if (dtrace_id2desc(dtp, (dtrace_id_t)id, dnp->dn_desc) != 0) {
2192                 xyerror(D_PDESC_INVAL, "invalid probe identifier %llu: %s\n",
2193                     (u_longlong_t)id, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2194         }
2195 
2196         return (dnp);
2197 }
2198 
2199 dt_node_t *
2200 dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts)
2201 {
2202         dt_node_t *dnp = dt_node_alloc(DT_NODE_CLAUSE);
2203 
2204         dnp->dn_pdescs = pdescs;
2205         dnp->dn_pred = pred;
2206         dnp->dn_acts = acts;
2207 
2208         yybegin(YYS_CLAUSE);
2209         return (dnp);
2210 }
2211 
2212 dt_node_t *
2213 dt_node_inline(dt_node_t *expr)
2214 {
2215         dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2216         dt_scope_t *dsp = &yypcb->pcb_dstack;
2217         dt_decl_t *ddp = dt_decl_top();
2218 
2219         char n[DT_TYPE_NAMELEN];
2220         dtrace_typeinfo_t dtt;
2221 
2222         dt_ident_t *idp, *rdp;
2223         dt_idnode_t *inp;
2224         dt_node_t *dnp;
2225 
2226         if (dt_decl_type(ddp, &dtt) != 0)
2227                 longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
2228 


3180         if (op == DT_TOK_LBRAC) {
3181                 if (lp->dn_kind == DT_NODE_IDENT) {
3182                         dt_idhash_t *dhp;
3183                         uint_t idkind;
3184 
3185                         if (lp->dn_op == DT_TOK_AGG) {
3186                                 dhp = dtp->dt_aggs;
3187                                 idp = dt_idhash_lookup(dhp, lp->dn_string + 1);
3188                                 idkind = DT_IDENT_AGG;
3189                         } else {
3190                                 dhp = dtp->dt_globals;
3191                                 idp = dt_idstack_lookup(
3192                                     &yypcb->pcb_globals, lp->dn_string);
3193                                 idkind = DT_IDENT_ARRAY;
3194                         }
3195 
3196                         if (idp == NULL || dt_ident_unref(idp))
3197                                 dt_xcook_ident(lp, dhp, idkind, B_TRUE);
3198                         else
3199                                 dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE);
3200                 } else
3201                         lp = dnp->dn_left = dt_node_cook(lp, 0);

3202 
3203                 /*
3204                  * Switch op to '+' for *(E1 + E2) array mode in these cases:
3205                  * (a) lp is a DT_IDENT_ARRAY variable that has already been
3206                  *      referenced using [] notation (dn_args != NULL).
3207                  * (b) lp is a non-ARRAY variable that has already been given
3208                  *      a type by assignment or declaration (!dt_ident_unref())
3209                  * (c) lp is neither a variable nor an aggregation
3210                  */
3211                 if (lp->dn_kind == DT_NODE_VAR) {
3212                         if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) {
3213                                 if (lp->dn_args != NULL)
3214                                         op = DT_TOK_ADD;
3215                         } else if (!dt_ident_unref(lp->dn_ident))
3216                                 op = DT_TOK_ADD;
3217                 } else if (lp->dn_kind != DT_NODE_AGG)

3218                         op = DT_TOK_ADD;
3219         }

3220 
3221         switch (op) {
3222         case DT_TOK_BAND:
3223         case DT_TOK_XOR:
3224         case DT_TOK_BOR:
3225                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3226                 rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);
3227 
3228                 if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {
3229                         xyerror(D_OP_INT, "operator %s requires operands of "
3230                             "integral type\n", opstr(op));
3231                 }
3232 
3233                 dt_node_promote(lp, rp, dnp); /* see K&R[A7.11-13] */
3234                 break;
3235 
3236         case DT_TOK_LSH:
3237         case DT_TOK_RSH:
3238                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3239                 rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);


3622                     dt_node_is_integer(rp) == 0) {
3623                         if (!dt_node_is_pointer(lp) || dt_node_is_vfptr(lp)) {
3624                                 xyerror(D_OP_VFPTR,
3625                                     "operator %s requires left-hand scalar "
3626                                     "operand of known size\n", opstr(op));
3627                         } else if (dt_node_is_integer(rp) == 0 &&
3628                             dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) {
3629                                 xyerror(D_OP_INCOMPAT, "operands have "
3630                                     "incompatible types: \"%s\" %s \"%s\"\n",
3631                                     dt_node_type_name(lp, n1, sizeof (n1)),
3632                                     opstr(op),
3633                                     dt_node_type_name(rp, n2, sizeof (n2)));
3634                         }
3635                 }
3636 asgn_common:
3637                 dt_assign_common(dnp);
3638                 break;
3639 
3640         case DT_TOK_PTR:
3641                 /*
3642                  * If the left-hand side of operator -> is the name "self",
3643                  * then we permit a TLS variable to be created or referenced.

3644                  */
3645                 if (lp->dn_kind == DT_NODE_IDENT &&
3646                     strcmp(lp->dn_string, "self") == 0) {
3647                         if (rp->dn_kind != DT_NODE_VAR) {
3648                                 dt_xcook_ident(rp, dtp->dt_tls,
3649                                     DT_IDENT_SCALAR, B_TRUE);
3650                         }
3651 
3652                         if (idflags != 0)
3653                                 rp = dt_node_cook(rp, idflags);
3654 
3655                         dnp->dn_right = dnp->dn_left; /* avoid freeing rp */
3656                         dt_node_free(dnp);
3657                         return (rp);
3658                 }
3659 
3660                 /*
3661                  * If the left-hand side of operator -> is the name "this",
3662                  * then we permit a local variable to be created or referenced.
3663                  */
3664                 if (lp->dn_kind == DT_NODE_IDENT &&
3665                     strcmp(lp->dn_string, "this") == 0) {
3666                         if (rp->dn_kind != DT_NODE_VAR) {
3667                                 dt_xcook_ident(rp, yypcb->pcb_locals,
3668                                     DT_IDENT_SCALAR, B_TRUE);
3669                         }
3670 
3671                         if (idflags != 0)
3672                                 rp = dt_node_cook(rp, idflags);
3673 
3674                         dnp->dn_right = dnp->dn_left; /* avoid freeing rp */

3675                         dt_node_free(dnp);
3676                         return (rp);
3677                 }
3678 
3679                 /*FALLTHRU*/
3680 
3681         case DT_TOK_DOT:
3682                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3683 
3684                 if (rp->dn_kind != DT_NODE_IDENT) {
3685                         xyerror(D_OP_IDENT, "operator %s must be followed by "
3686                             "an identifier\n", opstr(op));
3687                 }
3688 
3689                 if ((idp = dt_node_resolve(lp, DT_IDENT_XLSOU)) != NULL ||
3690                     (idp = dt_node_resolve(lp, DT_IDENT_XLPTR)) != NULL) {
3691                         /*
3692                          * If the left-hand side is a translated struct or ptr,
3693                          * the type of the left is the translation output type.
3694                          */
3695                         dt_xlator_t *dxp = idp->di_data;
3696 
3697                         if (dt_xlator_member(dxp, rp->dn_string) == NULL) {
3698                                 xyerror(D_XLATE_NOCONV,
3699                                     "translator does not define conversion "
3700                                     "for member: %s\n", rp->dn_string);


4479         dt_cook_none,           /* DT_NODE_INT */
4480         dt_cook_none,           /* DT_NODE_STRING */
4481         dt_cook_ident,          /* DT_NODE_IDENT */
4482         dt_cook_var,            /* DT_NODE_VAR */
4483         dt_cook_none,           /* DT_NODE_SYM */
4484         dt_cook_none,           /* DT_NODE_TYPE */
4485         dt_cook_func,           /* DT_NODE_FUNC */
4486         dt_cook_op1,            /* DT_NODE_OP1 */
4487         dt_cook_op2,            /* DT_NODE_OP2 */
4488         dt_cook_op3,            /* DT_NODE_OP3 */
4489         dt_cook_statement,      /* DT_NODE_DEXPR */
4490         dt_cook_statement,      /* DT_NODE_DFUNC */
4491         dt_cook_aggregation,    /* DT_NODE_AGG */
4492         dt_cook_none,           /* DT_NODE_PDESC */
4493         dt_cook_clause,         /* DT_NODE_CLAUSE */
4494         dt_cook_inline,         /* DT_NODE_INLINE */
4495         dt_cook_member,         /* DT_NODE_MEMBER */
4496         dt_cook_xlator,         /* DT_NODE_XLATOR */
4497         dt_cook_none,           /* DT_NODE_PROBE */
4498         dt_cook_provider,       /* DT_NODE_PROVIDER */
4499         dt_cook_none            /* DT_NODE_PROG */

4500 };
4501 
4502 /*
4503  * Recursively cook the parse tree starting at the specified node.  The idflags
4504  * parameter is used to indicate the type of reference (r/w) and is applied to
4505  * the resulting identifier if it is a D variable or D aggregation.
4506  */
4507 dt_node_t *
4508 dt_node_cook(dt_node_t *dnp, uint_t idflags)
4509 {
4510         int oldlineno = yylineno;
4511 
4512         yylineno = dnp->dn_line;
4513 


4514         dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags);
4515         dnp->dn_flags |= DT_NF_COOKED;
4516 
4517         if (dnp->dn_kind == DT_NODE_VAR || dnp->dn_kind == DT_NODE_AGG)
4518                 dnp->dn_ident->di_flags |= idflags;
4519 
4520         yylineno = oldlineno;
4521         return (dnp);
4522 }
4523 
4524 dtrace_attribute_t
4525 dt_node_list_cook(dt_node_t **pnp, uint_t idflags)
4526 {
4527         dtrace_attribute_t attr = _dtrace_defattr;
4528         dt_node_t *dnp, *nnp;
4529 
4530         for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {
4531                 nnp = dnp->dn_list;
4532                 dnp = *pnp = dt_node_cook(dnp, idflags);
4533                 attr = dt_attr_min(attr, dnp->dn_attr);


4596 void
4597 dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
4598 {
4599         if (dnp->dn_ctfp == DT_STR_CTFP(dtp) &&
4600             dnp->dn_type == DT_STR_TYPE(dtp)) {
4601                 tp->dtdt_kind = DIF_TYPE_STRING;
4602                 tp->dtdt_ckind = CTF_K_UNKNOWN;
4603         } else {
4604                 tp->dtdt_kind = DIF_TYPE_CTF;
4605                 tp->dtdt_ckind = ctf_type_kind(dnp->dn_ctfp,
4606                     ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
4607         }
4608 
4609         tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
4610             (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
4611             DIF_TF_BYREF : 0;
4612         tp->dtdt_pad = 0;
4613         tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
4614 }
4615 















4616 void
































































































































































4617 dt_node_printr(dt_node_t *dnp, FILE *fp, int depth)
4618 {
4619         char n[DT_TYPE_NAMELEN], buf[BUFSIZ], a[8];
4620         const dtrace_syminfo_t *dts;
4621         const dt_idnode_t *inp;
4622         dt_node_t *arg;
4623 
4624         (void) fprintf(fp, "%*s", depth * 2, "");
4625         (void) dt_attr_str(dnp->dn_attr, a, sizeof (a));
4626 
4627         if (dnp->dn_ctfp != NULL && dnp->dn_type != CTF_ERR &&
4628             ctf_type_name(dnp->dn_ctfp, dnp->dn_type, n, sizeof (n)) != NULL) {
4629                 (void) snprintf(buf, BUFSIZ, "type=<%s> attr=%s flags=", n, a);
4630         } else {
4631                 (void) snprintf(buf, BUFSIZ, "type=<%ld> attr=%s flags=",
4632                     dnp->dn_type, a);
4633         }
4634 
4635         if (dnp->dn_flags != 0) {
4636                 n[0] = '\0';


4706         case DT_NODE_FUNC:
4707                 (void) fprintf(fp, "FUNC %s (%s)\n",
4708                     dnp->dn_ident->di_name, buf);
4709 
4710                 for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {
4711                         dt_node_printr(arg, fp, depth + 1);
4712                         if (arg->dn_list != NULL)
4713                                 (void) fprintf(fp, "%*s,\n", depth * 2, "");
4714                 }
4715                 break;
4716 
4717         case DT_NODE_OP1:
4718                 (void) fprintf(fp, "OP1 %s (%s)\n", opstr(dnp->dn_op), buf);
4719                 dt_node_printr(dnp->dn_child, fp, depth + 1);
4720                 break;
4721 
4722         case DT_NODE_OP2:
4723                 (void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf);
4724                 dt_node_printr(dnp->dn_left, fp, depth + 1);
4725                 dt_node_printr(dnp->dn_right, fp, depth + 1);







4726                 break;
4727 
4728         case DT_NODE_OP3:
4729                 (void) fprintf(fp, "OP3 (%s)\n", buf);
4730                 dt_node_printr(dnp->dn_expr, fp, depth + 1);
4731                 (void) fprintf(fp, "%*s?\n", depth * 2, "");
4732                 dt_node_printr(dnp->dn_left, fp, depth + 1);
4733                 (void) fprintf(fp, "%*s:\n", depth * 2, "");
4734                 dt_node_printr(dnp->dn_right, fp, depth + 1);
4735                 break;
4736 
4737         case DT_NODE_DEXPR:
4738         case DT_NODE_DFUNC:
4739                 (void) fprintf(fp, "D EXPRESSION attr=%s\n", a);
4740                 dt_node_printr(dnp->dn_expr, fp, depth + 1);
4741                 break;
4742 
4743         case DT_NODE_AGG:
4744                 (void) fprintf(fp, "AGGREGATE @%s attr=%s [\n",
4745                     dnp->dn_ident->di_name, a);


4767                     dnp->dn_desc->dtpd_id);
4768                 break;
4769 
4770         case DT_NODE_CLAUSE:
4771                 (void) fprintf(fp, "CLAUSE attr=%s\n", a);
4772 
4773                 for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list)
4774                         dt_node_printr(arg, fp, depth + 1);
4775 
4776                 (void) fprintf(fp, "%*sCTXATTR %s\n", depth * 2, "",
4777                     dt_attr_str(dnp->dn_ctxattr, a, sizeof (a)));
4778 
4779                 if (dnp->dn_pred != NULL) {
4780                         (void) fprintf(fp, "%*sPREDICATE /\n", depth * 2, "");
4781                         dt_node_printr(dnp->dn_pred, fp, depth + 1);
4782                         (void) fprintf(fp, "%*s/\n", depth * 2, "");
4783                 }
4784 
4785                 for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list)
4786                         dt_node_printr(arg, fp, depth + 1);

4787                 break;
4788 
4789         case DT_NODE_INLINE:
4790                 inp = dnp->dn_ident->di_iarg;
4791 
4792                 (void) fprintf(fp, "INLINE %s (%s)\n",
4793                     dnp->dn_ident->di_name, buf);
4794                 dt_node_printr(inp->din_root, fp, depth + 1);
4795                 break;
4796 
4797         case DT_NODE_MEMBER:
4798                 (void) fprintf(fp, "MEMBER %s (%s)\n", dnp->dn_membname, buf);
4799                 if (dnp->dn_membexpr)
4800                         dt_node_printr(dnp->dn_membexpr, fp, depth + 1);
4801                 break;
4802 
4803         case DT_NODE_XLATOR:
4804                 (void) fprintf(fp, "XLATOR (%s)", buf);
4805 
4806                 if (ctf_type_name(dnp->dn_xlator->dx_src_ctfp,


4817                         dt_node_printr(arg, fp, depth + 1);
4818                 break;
4819 
4820         case DT_NODE_PROBE:
4821                 (void) fprintf(fp, "PROBE %s\n", dnp->dn_ident->di_name);
4822                 break;
4823 
4824         case DT_NODE_PROVIDER:
4825                 (void) fprintf(fp, "PROVIDER %s (%s)\n",
4826                     dnp->dn_provname, dnp->dn_provred ? "redecl" : "decl");
4827                 for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list)
4828                         dt_node_printr(arg, fp, depth + 1);
4829                 break;
4830 
4831         case DT_NODE_PROG:
4832                 (void) fprintf(fp, "PROGRAM attr=%s\n", a);
4833                 for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list)
4834                         dt_node_printr(arg, fp, depth + 1);
4835                 break;
4836 


















4837         default:
4838                 (void) fprintf(fp, "<bad node %p, kind %d>\n",
4839                     (void *)dnp, dnp->dn_kind);
4840         }
4841 }
4842 
4843 int
4844 dt_node_root(dt_node_t *dnp)
4845 {
4846         yypcb->pcb_root = dnp;
4847         return (0);
4848 }
4849 
4850 /*PRINTFLIKE3*/
4851 void
4852 dnerror(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...)
4853 {
4854         int oldlineno = yylineno;
4855         va_list ap;
4856 




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
  25  * Copyright (c) 2013, Joyent Inc. All rights reserved.

  26  */
  27 
  28 /*
  29  * DTrace D Language Parser
  30  *
  31  * The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the
  32  * parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles
  33  * the construction of the parse tree nodes and their syntactic validation.
  34  * The parse tree is constructed of dt_node_t structures (see <dt_parser.h>)
  35  * that are built in two passes: (1) the "create" pass, where the parse tree
  36  * nodes are allocated by calls from the grammar to dt_node_*() subroutines,
  37  * and (2) the "cook" pass, where nodes are coalesced, assigned D types, and
  38  * validated according to the syntactic rules of the language.
  39  *
  40  * All node allocations are performed using dt_node_alloc().  All node frees
  41  * during the parsing phase are performed by dt_node_free(), which frees node-
  42  * internal state but does not actually free the nodes.  All final node frees
  43  * are done as part of the end of dt_compile() or as part of destroying
  44  * persistent identifiers or translators which have embedded nodes.
  45  *


2120 
2121 dt_node_t *
2122 dt_node_statement(dt_node_t *expr)
2123 {
2124         dt_node_t *dnp;
2125 
2126         if (expr->dn_kind == DT_NODE_AGG)
2127                 return (expr);
2128 
2129         if (expr->dn_kind == DT_NODE_FUNC &&
2130             expr->dn_ident->di_kind == DT_IDENT_ACTFUNC)
2131                 dnp = dt_node_alloc(DT_NODE_DFUNC);
2132         else
2133                 dnp = dt_node_alloc(DT_NODE_DEXPR);
2134 
2135         dnp->dn_expr = expr;
2136         return (dnp);
2137 }
2138 
2139 dt_node_t *
2140 dt_node_if(dt_node_t *pred, dt_node_t *acts, dt_node_t *else_acts)
2141 {
2142         dt_node_t *dnp = dt_node_alloc(DT_NODE_IF);
2143         dnp->dn_conditional = pred;
2144         dnp->dn_body = acts;
2145         dnp->dn_alternate_body = else_acts;
2146 
2147         return (dnp);
2148 }
2149 
2150 dt_node_t *
2151 dt_node_pdesc_by_name(char *spec)
2152 {
2153         dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2154         dt_node_t *dnp;
2155 
2156         if (spec == NULL)
2157                 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2158 
2159         dnp = dt_node_alloc(DT_NODE_PDESC);
2160         dnp->dn_spec = spec;
2161         dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t));
2162 
2163         if (dnp->dn_desc == NULL)
2164                 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2165 
2166         if (dtrace_xstr2desc(dtp, yypcb->pcb_pspec, dnp->dn_spec,
2167             yypcb->pcb_sargc, yypcb->pcb_sargv, dnp->dn_desc) != 0) {
2168                 xyerror(D_PDESC_INVAL, "invalid probe description \"%s\": %s\n",
2169                     dnp->dn_spec, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2170         }


2199                     names[yypcb->pcb_pspec]);
2200         }
2201 
2202         if (dtrace_id2desc(dtp, (dtrace_id_t)id, dnp->dn_desc) != 0) {
2203                 xyerror(D_PDESC_INVAL, "invalid probe identifier %llu: %s\n",
2204                     (u_longlong_t)id, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2205         }
2206 
2207         return (dnp);
2208 }
2209 
2210 dt_node_t *
2211 dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts)
2212 {
2213         dt_node_t *dnp = dt_node_alloc(DT_NODE_CLAUSE);
2214 
2215         dnp->dn_pdescs = pdescs;
2216         dnp->dn_pred = pred;
2217         dnp->dn_acts = acts;
2218 

2219         return (dnp);
2220 }
2221 
2222 dt_node_t *
2223 dt_node_inline(dt_node_t *expr)
2224 {
2225         dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2226         dt_scope_t *dsp = &yypcb->pcb_dstack;
2227         dt_decl_t *ddp = dt_decl_top();
2228 
2229         char n[DT_TYPE_NAMELEN];
2230         dtrace_typeinfo_t dtt;
2231 
2232         dt_ident_t *idp, *rdp;
2233         dt_idnode_t *inp;
2234         dt_node_t *dnp;
2235 
2236         if (dt_decl_type(ddp, &dtt) != 0)
2237                 longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
2238 


3190         if (op == DT_TOK_LBRAC) {
3191                 if (lp->dn_kind == DT_NODE_IDENT) {
3192                         dt_idhash_t *dhp;
3193                         uint_t idkind;
3194 
3195                         if (lp->dn_op == DT_TOK_AGG) {
3196                                 dhp = dtp->dt_aggs;
3197                                 idp = dt_idhash_lookup(dhp, lp->dn_string + 1);
3198                                 idkind = DT_IDENT_AGG;
3199                         } else {
3200                                 dhp = dtp->dt_globals;
3201                                 idp = dt_idstack_lookup(
3202                                     &yypcb->pcb_globals, lp->dn_string);
3203                                 idkind = DT_IDENT_ARRAY;
3204                         }
3205 
3206                         if (idp == NULL || dt_ident_unref(idp))
3207                                 dt_xcook_ident(lp, dhp, idkind, B_TRUE);
3208                         else
3209                                 dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE);
3210                 } else {
3211                         lp = dnp->dn_left = dt_node_cook(lp, 0);
3212                 }
3213 
3214                 /*
3215                  * Switch op to '+' for *(E1 + E2) array mode in these cases:
3216                  * (a) lp is a DT_IDENT_ARRAY variable that has already been
3217                  *      referenced using [] notation (dn_args != NULL).
3218                  * (b) lp is a non-ARRAY variable that has already been given
3219                  *      a type by assignment or declaration (!dt_ident_unref())
3220                  * (c) lp is neither a variable nor an aggregation
3221                  */
3222                 if (lp->dn_kind == DT_NODE_VAR) {
3223                         if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) {
3224                                 if (lp->dn_args != NULL)
3225                                         op = DT_TOK_ADD;
3226                         } else if (!dt_ident_unref(lp->dn_ident)) {
3227                                 op = DT_TOK_ADD;
3228                         }
3229                 } else if (lp->dn_kind != DT_NODE_AGG) {
3230                         op = DT_TOK_ADD;
3231                 }
3232         }
3233 
3234         switch (op) {
3235         case DT_TOK_BAND:
3236         case DT_TOK_XOR:
3237         case DT_TOK_BOR:
3238                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3239                 rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);
3240 
3241                 if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {
3242                         xyerror(D_OP_INT, "operator %s requires operands of "
3243                             "integral type\n", opstr(op));
3244                 }
3245 
3246                 dt_node_promote(lp, rp, dnp); /* see K&R[A7.11-13] */
3247                 break;
3248 
3249         case DT_TOK_LSH:
3250         case DT_TOK_RSH:
3251                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3252                 rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);


3635                     dt_node_is_integer(rp) == 0) {
3636                         if (!dt_node_is_pointer(lp) || dt_node_is_vfptr(lp)) {
3637                                 xyerror(D_OP_VFPTR,
3638                                     "operator %s requires left-hand scalar "
3639                                     "operand of known size\n", opstr(op));
3640                         } else if (dt_node_is_integer(rp) == 0 &&
3641                             dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) {
3642                                 xyerror(D_OP_INCOMPAT, "operands have "
3643                                     "incompatible types: \"%s\" %s \"%s\"\n",
3644                                     dt_node_type_name(lp, n1, sizeof (n1)),
3645                                     opstr(op),
3646                                     dt_node_type_name(rp, n2, sizeof (n2)));
3647                         }
3648                 }
3649 asgn_common:
3650                 dt_assign_common(dnp);
3651                 break;
3652 
3653         case DT_TOK_PTR:
3654                 /*
3655                  * If the left-hand side of operator -> is one of the
3656                  * scoping keywords, permit a local or thread
3657                  * variable to be created or referenced.
3658                  */
3659                 if (lp->dn_kind == DT_NODE_IDENT) {
3660                         dt_idhash_t *dhp = NULL;




3661 
3662                         if (strcmp(lp->dn_string, "self") == 0) {
3663                                 dhp = dtp->dt_tls;
3664                         } else if (strcmp(lp->dn_string, "this") == 0) {
3665                                 dhp = yypcb->pcb_locals;


3666                         }
3667                         if (dhp != NULL) {






3668                                 if (rp->dn_kind != DT_NODE_VAR) {
3669                                         dt_xcook_ident(rp, dhp,
3670                                             DT_IDENT_SCALAR, B_TRUE);
3671                                 }
3672 
3673                                 if (idflags != 0)
3674                                         rp = dt_node_cook(rp, idflags);
3675 
3676                                 /* avoid freeing rp */
3677                                 dnp->dn_right = dnp->dn_left;
3678                                 dt_node_free(dnp);
3679                                 return (rp);
3680                         }
3681                 }
3682                 /*FALLTHRU*/

3683         case DT_TOK_DOT:
3684                 lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
3685 
3686                 if (rp->dn_kind != DT_NODE_IDENT) {
3687                         xyerror(D_OP_IDENT, "operator %s must be followed by "
3688                             "an identifier\n", opstr(op));
3689                 }
3690 
3691                 if ((idp = dt_node_resolve(lp, DT_IDENT_XLSOU)) != NULL ||
3692                     (idp = dt_node_resolve(lp, DT_IDENT_XLPTR)) != NULL) {
3693                         /*
3694                          * If the left-hand side is a translated struct or ptr,
3695                          * the type of the left is the translation output type.
3696                          */
3697                         dt_xlator_t *dxp = idp->di_data;
3698 
3699                         if (dt_xlator_member(dxp, rp->dn_string) == NULL) {
3700                                 xyerror(D_XLATE_NOCONV,
3701                                     "translator does not define conversion "
3702                                     "for member: %s\n", rp->dn_string);


4481         dt_cook_none,           /* DT_NODE_INT */
4482         dt_cook_none,           /* DT_NODE_STRING */
4483         dt_cook_ident,          /* DT_NODE_IDENT */
4484         dt_cook_var,            /* DT_NODE_VAR */
4485         dt_cook_none,           /* DT_NODE_SYM */
4486         dt_cook_none,           /* DT_NODE_TYPE */
4487         dt_cook_func,           /* DT_NODE_FUNC */
4488         dt_cook_op1,            /* DT_NODE_OP1 */
4489         dt_cook_op2,            /* DT_NODE_OP2 */
4490         dt_cook_op3,            /* DT_NODE_OP3 */
4491         dt_cook_statement,      /* DT_NODE_DEXPR */
4492         dt_cook_statement,      /* DT_NODE_DFUNC */
4493         dt_cook_aggregation,    /* DT_NODE_AGG */
4494         dt_cook_none,           /* DT_NODE_PDESC */
4495         dt_cook_clause,         /* DT_NODE_CLAUSE */
4496         dt_cook_inline,         /* DT_NODE_INLINE */
4497         dt_cook_member,         /* DT_NODE_MEMBER */
4498         dt_cook_xlator,         /* DT_NODE_XLATOR */
4499         dt_cook_none,           /* DT_NODE_PROBE */
4500         dt_cook_provider,       /* DT_NODE_PROVIDER */
4501         dt_cook_none,           /* DT_NODE_PROG */
4502         dt_cook_none,           /* DT_NODE_IF */
4503 };
4504 
4505 /*
4506  * Recursively cook the parse tree starting at the specified node.  The idflags
4507  * parameter is used to indicate the type of reference (r/w) and is applied to
4508  * the resulting identifier if it is a D variable or D aggregation.
4509  */
4510 dt_node_t *
4511 dt_node_cook(dt_node_t *dnp, uint_t idflags)
4512 {
4513         int oldlineno = yylineno;
4514 
4515         yylineno = dnp->dn_line;
4516 
4517         assert(dnp->dn_kind <
4518             sizeof (dt_cook_funcs) / sizeof (dt_cook_funcs[0]));
4519         dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags);
4520         dnp->dn_flags |= DT_NF_COOKED;
4521 
4522         if (dnp->dn_kind == DT_NODE_VAR || dnp->dn_kind == DT_NODE_AGG)
4523                 dnp->dn_ident->di_flags |= idflags;
4524 
4525         yylineno = oldlineno;
4526         return (dnp);
4527 }
4528 
4529 dtrace_attribute_t
4530 dt_node_list_cook(dt_node_t **pnp, uint_t idflags)
4531 {
4532         dtrace_attribute_t attr = _dtrace_defattr;
4533         dt_node_t *dnp, *nnp;
4534 
4535         for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {
4536                 nnp = dnp->dn_list;
4537                 dnp = *pnp = dt_node_cook(dnp, idflags);
4538                 attr = dt_attr_min(attr, dnp->dn_attr);


4601 void
4602 dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
4603 {
4604         if (dnp->dn_ctfp == DT_STR_CTFP(dtp) &&
4605             dnp->dn_type == DT_STR_TYPE(dtp)) {
4606                 tp->dtdt_kind = DIF_TYPE_STRING;
4607                 tp->dtdt_ckind = CTF_K_UNKNOWN;
4608         } else {
4609                 tp->dtdt_kind = DIF_TYPE_CTF;
4610                 tp->dtdt_ckind = ctf_type_kind(dnp->dn_ctfp,
4611                     ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
4612         }
4613 
4614         tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
4615             (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
4616             DIF_TF_BYREF : 0;
4617         tp->dtdt_pad = 0;
4618         tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
4619 }
4620 
4621 /*
4622  * Output the parse tree as D.  The "-xtree=8" argument will call this
4623  * function to print out the program after any syntactic sugar
4624  * transformations have been applied (e.g. to implement "if").  The
4625  * resulting output can be used to understand the transformations
4626  * applied by these features, or to run such a script on a system that
4627  * does not support these features
4628  *
4629  * Note that the output does not express precisely the same program as
4630  * the input.  In particular:
4631  *  - Only the clauses are output.  #pragma options, variable
4632  *    declarations, etc. are excluded.
4633  *  - Command argument substitution has already been done, so the output
4634  *    will not contain e.g. $$1, but rather the substituted string.
4635  */
4636 void
4637 dt_printd(dt_node_t *dnp, FILE *fp, int depth)
4638 {
4639         dt_node_t *arg;
4640 
4641         switch (dnp->dn_kind) {
4642         case DT_NODE_INT:
4643                 (void) fprintf(fp, "0x%llx", (u_longlong_t)dnp->dn_value);
4644                 if (!(dnp->dn_flags & DT_NF_SIGNED))
4645                         (void) fprintf(fp, "u");
4646                 break;
4647 
4648         case DT_NODE_STRING: {
4649                 char *escd = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));
4650                 (void) fprintf(fp, "\"%s\"", escd);
4651                 free(escd);
4652                 break;
4653         }
4654 
4655         case DT_NODE_IDENT:
4656                 (void) fprintf(fp, "%s", dnp->dn_string);
4657                 break;
4658 
4659         case DT_NODE_VAR:
4660                 (void) fprintf(fp, "%s%s",
4661                     (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" :
4662                     (dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "",
4663                     dnp->dn_ident->di_name);
4664 
4665                 if (dnp->dn_args != NULL) {
4666                         (void) fprintf(fp, "[");
4667 
4668                         for (arg = dnp->dn_args; arg != NULL;
4669                             arg = arg->dn_list) {
4670                                 dt_printd(arg, fp, 0);
4671                                 if (arg->dn_list != NULL)
4672                                         (void) fprintf(fp, ", ");
4673                         }
4674 
4675                         (void) fprintf(fp, "]");
4676                 }
4677                 break;
4678 
4679         case DT_NODE_SYM: {
4680                 const dtrace_syminfo_t *dts = dnp->dn_ident->di_data;
4681                 (void) fprintf(fp, "%s`%s", dts->dts_object, dts->dts_name);
4682                 break;
4683         }
4684         case DT_NODE_FUNC:
4685                 (void) fprintf(fp, "%s(", dnp->dn_ident->di_name);
4686 
4687                 for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {
4688                         dt_printd(arg, fp, 0);
4689                         if (arg->dn_list != NULL)
4690                                 (void) fprintf(fp, ", ");
4691                 }
4692                 (void) fprintf(fp, ")");
4693                 break;
4694 
4695         case DT_NODE_OP1:
4696                 (void) fprintf(fp, "%s(", opstr(dnp->dn_op));
4697                 dt_printd(dnp->dn_child, fp, 0);
4698                 (void) fprintf(fp, ")");
4699                 break;
4700 
4701         case DT_NODE_OP2:
4702                 (void) fprintf(fp, "(");
4703                 dt_printd(dnp->dn_left, fp, 0);
4704                 if (dnp->dn_op == DT_TOK_LPAR) {
4705                         (void) fprintf(fp, ")");
4706                         dt_printd(dnp->dn_right, fp, 0);
4707                         break;
4708                 }
4709                 if (dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT ||
4710                     dnp->dn_op == DT_TOK_LBRAC)
4711                         (void) fprintf(fp, "%s", opstr(dnp->dn_op));
4712                 else
4713                         (void) fprintf(fp, " %s ", opstr(dnp->dn_op));
4714                 dt_printd(dnp->dn_right, fp, 0);
4715                 if (dnp->dn_op == DT_TOK_LBRAC) {
4716                         dt_node_t *ln = dnp->dn_right;
4717                         while (ln->dn_list != NULL) {
4718                                 (void) fprintf(fp, ", ");
4719                                 dt_printd(ln->dn_list, fp, depth);
4720                                 ln = ln->dn_list;
4721                         }
4722                         (void) fprintf(fp, "]");
4723                 }
4724                 (void) fprintf(fp, ")");
4725                 break;
4726 
4727         case DT_NODE_OP3:
4728                 (void) fprintf(fp, "(");
4729                 dt_printd(dnp->dn_expr, fp, 0);
4730                 (void) fprintf(fp, " ? ");
4731                 dt_printd(dnp->dn_left, fp, 0);
4732                 (void) fprintf(fp, " : ");
4733                 dt_printd(dnp->dn_right, fp, 0);
4734                 (void) fprintf(fp, ")");
4735                 break;
4736 
4737         case DT_NODE_DEXPR:
4738         case DT_NODE_DFUNC:
4739                 (void) fprintf(fp, "%*s", depth * 8, "");
4740                 dt_printd(dnp->dn_expr, fp, depth + 1);
4741                 (void) fprintf(fp, ";\n");
4742                 break;
4743 
4744         case DT_NODE_PDESC:
4745                 (void) fprintf(fp, "%s:%s:%s:%s",
4746                     dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,
4747                     dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name);
4748                 break;
4749 
4750         case DT_NODE_CLAUSE:
4751                 for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) {
4752                         dt_printd(arg, fp, 0);
4753                         if (arg->dn_list != NULL)
4754                                 (void) fprintf(fp, ",");
4755                         (void) fprintf(fp, "\n");
4756                 }
4757 
4758                 if (dnp->dn_pred != NULL) {
4759                         (void) fprintf(fp, "/");
4760                         dt_printd(dnp->dn_pred, fp, 0);
4761                         (void) fprintf(fp, "/\n");
4762                 }
4763                         (void) fprintf(fp, "{\n");
4764 
4765                 for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list)
4766                         dt_printd(arg, fp, depth + 1);
4767                 (void) fprintf(fp, "}\n");
4768                 (void) fprintf(fp, "\n");
4769                 break;
4770 
4771         case DT_NODE_IF:
4772                 (void) fprintf(fp, "%*sif (", depth * 8, "");
4773                 dt_printd(dnp->dn_conditional, fp, 0);
4774                 (void) fprintf(fp, ") {\n");
4775 
4776                 for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list)
4777                         dt_printd(arg, fp, depth + 1);
4778                 if (dnp->dn_alternate_body == NULL) {
4779                         (void) fprintf(fp, "%*s}\n", depth * 8, "");
4780                 } else {
4781                         (void) fprintf(fp, "%*s} else {\n", depth * 8, "");
4782                         for (arg = dnp->dn_alternate_body; arg != NULL;
4783                             arg = arg->dn_list)
4784                                 dt_printd(arg, fp, depth + 1);
4785                         (void) fprintf(fp, "%*s}\n", depth * 8, "");
4786                 }
4787 
4788                 break;
4789 
4790         default:
4791                 (void) fprintf(fp, "/* bad node %p, kind %d */\n",
4792                     (void *)dnp, dnp->dn_kind);
4793         }
4794 }
4795 
4796 void
4797 dt_node_printr(dt_node_t *dnp, FILE *fp, int depth)
4798 {
4799         char n[DT_TYPE_NAMELEN], buf[BUFSIZ], a[8];
4800         const dtrace_syminfo_t *dts;
4801         const dt_idnode_t *inp;
4802         dt_node_t *arg;
4803 
4804         (void) fprintf(fp, "%*s", depth * 2, "");
4805         (void) dt_attr_str(dnp->dn_attr, a, sizeof (a));
4806 
4807         if (dnp->dn_ctfp != NULL && dnp->dn_type != CTF_ERR &&
4808             ctf_type_name(dnp->dn_ctfp, dnp->dn_type, n, sizeof (n)) != NULL) {
4809                 (void) snprintf(buf, BUFSIZ, "type=<%s> attr=%s flags=", n, a);
4810         } else {
4811                 (void) snprintf(buf, BUFSIZ, "type=<%ld> attr=%s flags=",
4812                     dnp->dn_type, a);
4813         }
4814 
4815         if (dnp->dn_flags != 0) {
4816                 n[0] = '\0';


4886         case DT_NODE_FUNC:
4887                 (void) fprintf(fp, "FUNC %s (%s)\n",
4888                     dnp->dn_ident->di_name, buf);
4889 
4890                 for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {
4891                         dt_node_printr(arg, fp, depth + 1);
4892                         if (arg->dn_list != NULL)
4893                                 (void) fprintf(fp, "%*s,\n", depth * 2, "");
4894                 }
4895                 break;
4896 
4897         case DT_NODE_OP1:
4898                 (void) fprintf(fp, "OP1 %s (%s)\n", opstr(dnp->dn_op), buf);
4899                 dt_node_printr(dnp->dn_child, fp, depth + 1);
4900                 break;
4901 
4902         case DT_NODE_OP2:
4903                 (void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf);
4904                 dt_node_printr(dnp->dn_left, fp, depth + 1);
4905                 dt_node_printr(dnp->dn_right, fp, depth + 1);
4906                 if (dnp->dn_op == DT_TOK_LBRAC) {
4907                         dt_node_t *ln = dnp->dn_right;
4908                         while (ln->dn_list != NULL) {
4909                                 dt_node_printr(ln->dn_list, fp, depth + 1);
4910                                 ln = ln->dn_list;
4911                         }
4912                 }
4913                 break;
4914 
4915         case DT_NODE_OP3:
4916                 (void) fprintf(fp, "OP3 (%s)\n", buf);
4917                 dt_node_printr(dnp->dn_expr, fp, depth + 1);
4918                 (void) fprintf(fp, "%*s?\n", depth * 2, "");
4919                 dt_node_printr(dnp->dn_left, fp, depth + 1);
4920                 (void) fprintf(fp, "%*s:\n", depth * 2, "");
4921                 dt_node_printr(dnp->dn_right, fp, depth + 1);
4922                 break;
4923 
4924         case DT_NODE_DEXPR:
4925         case DT_NODE_DFUNC:
4926                 (void) fprintf(fp, "D EXPRESSION attr=%s\n", a);
4927                 dt_node_printr(dnp->dn_expr, fp, depth + 1);
4928                 break;
4929 
4930         case DT_NODE_AGG:
4931                 (void) fprintf(fp, "AGGREGATE @%s attr=%s [\n",
4932                     dnp->dn_ident->di_name, a);


4954                     dnp->dn_desc->dtpd_id);
4955                 break;
4956 
4957         case DT_NODE_CLAUSE:
4958                 (void) fprintf(fp, "CLAUSE attr=%s\n", a);
4959 
4960                 for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list)
4961                         dt_node_printr(arg, fp, depth + 1);
4962 
4963                 (void) fprintf(fp, "%*sCTXATTR %s\n", depth * 2, "",
4964                     dt_attr_str(dnp->dn_ctxattr, a, sizeof (a)));
4965 
4966                 if (dnp->dn_pred != NULL) {
4967                         (void) fprintf(fp, "%*sPREDICATE /\n", depth * 2, "");
4968                         dt_node_printr(dnp->dn_pred, fp, depth + 1);
4969                         (void) fprintf(fp, "%*s/\n", depth * 2, "");
4970                 }
4971 
4972                 for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list)
4973                         dt_node_printr(arg, fp, depth + 1);
4974                 (void) fprintf(fp, "\n");
4975                 break;
4976 
4977         case DT_NODE_INLINE:
4978                 inp = dnp->dn_ident->di_iarg;
4979 
4980                 (void) fprintf(fp, "INLINE %s (%s)\n",
4981                     dnp->dn_ident->di_name, buf);
4982                 dt_node_printr(inp->din_root, fp, depth + 1);
4983                 break;
4984 
4985         case DT_NODE_MEMBER:
4986                 (void) fprintf(fp, "MEMBER %s (%s)\n", dnp->dn_membname, buf);
4987                 if (dnp->dn_membexpr)
4988                         dt_node_printr(dnp->dn_membexpr, fp, depth + 1);
4989                 break;
4990 
4991         case DT_NODE_XLATOR:
4992                 (void) fprintf(fp, "XLATOR (%s)", buf);
4993 
4994                 if (ctf_type_name(dnp->dn_xlator->dx_src_ctfp,


5005                         dt_node_printr(arg, fp, depth + 1);
5006                 break;
5007 
5008         case DT_NODE_PROBE:
5009                 (void) fprintf(fp, "PROBE %s\n", dnp->dn_ident->di_name);
5010                 break;
5011 
5012         case DT_NODE_PROVIDER:
5013                 (void) fprintf(fp, "PROVIDER %s (%s)\n",
5014                     dnp->dn_provname, dnp->dn_provred ? "redecl" : "decl");
5015                 for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list)
5016                         dt_node_printr(arg, fp, depth + 1);
5017                 break;
5018 
5019         case DT_NODE_PROG:
5020                 (void) fprintf(fp, "PROGRAM attr=%s\n", a);
5021                 for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list)
5022                         dt_node_printr(arg, fp, depth + 1);
5023                 break;
5024 
5025         case DT_NODE_IF:
5026                 (void) fprintf(fp, "IF attr=%s CONDITION:\n", a);
5027 
5028                 dt_node_printr(dnp->dn_conditional, fp, depth + 1);
5029 
5030                 (void) fprintf(fp, "%*sIF BODY: \n", depth * 2, "");
5031                 for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list)
5032                         dt_node_printr(arg, fp, depth + 1);
5033 
5034                 if (dnp->dn_alternate_body != NULL) {
5035                         (void) fprintf(fp, "%*sIF ELSE: \n", depth * 2, "");
5036                         for (arg = dnp->dn_alternate_body; arg != NULL;
5037                             arg = arg->dn_list)
5038                                 dt_node_printr(arg, fp, depth + 1);
5039                 }
5040 
5041                 break;
5042 
5043         default:
5044                 (void) fprintf(fp, "<bad node %p, kind %d>\n",
5045                     (void *)dnp, dnp->dn_kind);
5046         }
5047 }
5048 
5049 int
5050 dt_node_root(dt_node_t *dnp)
5051 {
5052         yypcb->pcb_root = dnp;
5053         return (0);
5054 }
5055 
5056 /*PRINTFLIKE3*/
5057 void
5058 dnerror(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...)
5059 {
5060         int oldlineno = yylineno;
5061         va_list ap;
5062