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
|