📄 dt_parser.c
字号:
rp->dn_value = rp->dn_value >> n; } dt_node_type_propagate(lp, rp); dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr)); dt_node_free(lp); return (rp); } /* * If no immediate optimizations are available, create an new OP2 node * and glue the left and right children into place and return. */ dnp = dt_node_alloc(DT_NODE_OP2); assert(op <= USHRT_MAX); dnp->dn_op = (ushort_t)op; dnp->dn_left = lp; dnp->dn_right = rp; return (dnp);}dt_node_t *dt_node_op3(dt_node_t *expr, dt_node_t *lp, dt_node_t *rp){ dt_node_t *dnp; if (expr->dn_kind == DT_NODE_INT) return (expr->dn_value != 0 ? lp : rp); dnp = dt_node_alloc(DT_NODE_OP3); dnp->dn_op = DT_TOK_QUESTION; dnp->dn_expr = expr; dnp->dn_left = lp; dnp->dn_right = rp; return (dnp);}dt_node_t *dt_node_statement(dt_node_t *expr){ dt_node_t *dnp; if (expr->dn_kind == DT_NODE_AGG) return (expr); if (expr->dn_kind == DT_NODE_FUNC && expr->dn_ident->di_kind == DT_IDENT_ACTFUNC) dnp = dt_node_alloc(DT_NODE_DFUNC); else dnp = dt_node_alloc(DT_NODE_DEXPR); dnp->dn_expr = expr; return (dnp);}dt_node_t *dt_node_pdesc_by_name(char *spec){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *dnp; if (spec == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); dnp = dt_node_alloc(DT_NODE_PDESC); dnp->dn_spec = spec; dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t)); if (dnp->dn_desc == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (dtrace_xstr2desc(dtp, yypcb->pcb_pspec, dnp->dn_spec, yypcb->pcb_sargc, yypcb->pcb_sargv, dnp->dn_desc) != 0) { xyerror(D_PDESC_INVAL, "invalid probe description \"%s\": %s\n", dnp->dn_spec, dtrace_errmsg(dtp, dtrace_errno(dtp))); } free(dnp->dn_spec); dnp->dn_spec = NULL; return (dnp);}dt_node_t *dt_node_pdesc_by_id(uintmax_t id){ static const char *const names[] = { "providers", "modules", "functions" }; dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *dnp = dt_node_alloc(DT_NODE_PDESC); if ((dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t))) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (id > UINT_MAX) { xyerror(D_PDESC_INVAL, "identifier %llu exceeds maximum " "probe id\n", (u_longlong_t)id); } if (yypcb->pcb_pspec != DTRACE_PROBESPEC_NAME) { xyerror(D_PDESC_INVAL, "probe identifier %llu not permitted " "when specifying %s\n", (u_longlong_t)id, names[yypcb->pcb_pspec]); } if (dtrace_id2desc(dtp, (dtrace_id_t)id, dnp->dn_desc) != 0) { xyerror(D_PDESC_INVAL, "invalid probe identifier %llu: %s\n", (u_longlong_t)id, dtrace_errmsg(dtp, dtrace_errno(dtp))); } return (dnp);}dt_node_t *dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts){ dt_node_t *dnp = dt_node_alloc(DT_NODE_CLAUSE); dnp->dn_pdescs = pdescs; dnp->dn_pred = pred; dnp->dn_acts = acts; yybegin(YYS_CLAUSE); return (dnp);}dt_node_t *dt_node_inline(dt_decl_t *ddp, char *name, dt_node_t *expr){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; dtrace_typeinfo_t dtt; dtrace_attribute_t attr; int err; dt_idnode_t *inp; dt_ident_t *idp; dt_node_t *dnp; err = dt_decl_type(ddp, &dtt); dt_decl_free(ddp); if (err != 0) longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); /* * Unlike most constructors, we need to explicitly cook the right-hand * side of the inline definition immediately to prevent recursion. If * the right-hand side uses the inline itself, the cook will fail. */ expr = dt_node_cook(expr, DT_IDFLG_REF); attr = dt_attr_min(_dtrace_defattr, expr->dn_attr); if ((idp = dt_idhash_lookup(dtp->dt_globals, name)) != NULL) { free(name); xyerror(D_DECL_IDRED, "identifier redefined: %s\n\t current: " "inline definition\n\tprevious: %s %s\n", idp->di_name, dt_idkind_name(idp->di_kind), (idp->di_flags & DT_IDFLG_INLINE) ? "inline" : ""); } dt_dprintf("create inline definition %s\n", name); idp = dt_idhash_insert(dtp->dt_globals, name, DT_IDENT_SCALAR, DT_IDFLG_INLINE | DT_IDFLG_REF, 0, attr, 0, &dt_idops_inline, NULL, dtp->dt_gen); free(name); if (idp == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if ((inp = malloc(sizeof (dt_idnode_t))) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); inp->din_list = yypcb->pcb_list; inp->din_root = expr; yybegin(YYS_CLAUSE); idp->di_data = inp; if (dt_node_is_dynamic(expr)) { dt_ident_t *rdp = dt_ident_resolve(expr->dn_ident); idp->di_kind = rdp->di_kind; idp->di_flags |= (rdp->di_flags & (DT_IDFLG_WRITE | DT_IDFLG_USER | DT_IDFLG_PRIM)); idp->di_ctfp = expr->dn_ctfp; idp->di_type = expr->dn_type; } else { if (expr->dn_kind == DT_NODE_VAR || expr->dn_kind == DT_NODE_SYM) { idp->di_flags |= (expr->dn_ident->di_flags & (DT_IDFLG_WRITE | DT_IDFLG_USER | DT_IDFLG_PRIM)); } idp->di_ctfp = dtt.dtt_ctfp; idp->di_type = dtt.dtt_type; } dnp = dt_node_alloc(DT_NODE_INLINE); dnp->dn_ident = idp; dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); dt_node_attr_assign(dnp, _dtrace_defattr); dnp->dn_flags &= ~DT_NF_COOKED; return (dt_node_cook(dnp, DT_IDFLG_REF));}dt_node_t *dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr){ dtrace_typeinfo_t dtt; dt_node_t *dnp; int err; if (ddp != NULL) { err = dt_decl_type(ddp, &dtt); dt_decl_free(ddp); if (err != 0) longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); } dnp = dt_node_alloc(DT_NODE_MEMBER); dnp->dn_membname = name; dnp->dn_membexpr = expr; if (ddp != NULL) dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); return (dnp);}dt_node_t *dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; dtrace_typeinfo_t src, dst; dt_node_t sn, dn; dt_xlator_t *dxp; dt_node_t *dnp; int edst, esrc; char n1[DT_TYPE_NAMELEN]; char n2[DT_TYPE_NAMELEN]; edst = dt_decl_type(ddp, &dst); dt_decl_free(ddp); esrc = dt_decl_type(sdp, &src); dt_decl_free(sdp); if (edst != 0 || esrc != 0) { free(name); longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); } bzero(&sn, sizeof (sn)); dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type); bzero(&dn, sizeof (dn)); dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type); if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) { xyerror(D_XLATE_REDECL, "translator from %s to %s has already been declared\n", dt_node_type_name(&sn, n1, sizeof (n1)), dt_node_type_name(&dn, n2, sizeof (n2))); } dxp = dt_xlator_create(dtp, &src, &dst, name, members, yypcb->pcb_list); yybegin(YYS_CLAUSE); free(name); if (dxp == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); dnp = dt_node_alloc(DT_NODE_XLATOR); dnp->dn_xlator = dxp; dnp->dn_members = members; return (dt_node_cook(dnp, DT_IDFLG_REF));}/* * Examine the list of formal parameters 'flist' and determine if the formal * name fnp->dn_string is defined in this list (B_TRUE) or not (B_FALSE). * If 'fnp' is in 'flist', do not search beyond 'fnp' itself in 'flist'. */static intdt_node_probe_protoform(dt_node_t *fnp, dt_node_t *flist){ dt_node_t *dnp; for (dnp = flist; dnp != fnp && dnp != NULL; dnp = dnp->dn_list) { if (dnp->dn_string != NULL && strcmp(dnp->dn_string, fnp->dn_string) == 0) return (B_TRUE); } return (B_FALSE);}/* * Common code for parsing a probe definition's prototype 'plist', of which * there can be two: one for native arguments at the probe site and one for * translated arguments presented to DTrace consumers. If 'defined' is TRUE, * we demand that every formal parameter have a name and be present in 'flist'. * If 'defined' is false, we require that named parameters not be in 'flist'. */static intdt_node_probe_prototype(const char *pname, const char *desc, dt_node_t *plist, dt_node_t *flist, int defined){ char n[DT_TYPE_NAMELEN]; dt_node_t *dnp; int i = 0, v = 0; for (dnp = plist; dnp != NULL; dnp = dnp->dn_list, i++) { if (dt_node_is_dynamic(dnp)) { xyerror(D_DECL_FUNCTYPE, "%s type may not be " "used in probe %s %s prototype: param #%d\n", dt_node_type_name(dnp, n, sizeof (n)), pname, desc, i + 1); } if (dnp->dn_type == CTF_ERR) { xyerror(D_DECL_FUNCTYPE, "probe %s %s prototype may " "not use variable argument list\n", pname, desc); } if (dnp->dn_string != NULL && dt_node_probe_protoform(dnp, flist) != defined) { xyerror(D_DECL_PARMNAME, "formal parameter %s is %s " "defined in probe %s %s prototype: param #%d\n", dnp->dn_string, defined ? "not" : "already", pname, desc, i + 1); } if (dt_node_is_void(dnp)) v++; /* count number of void parameters for below */ else if (dnp->dn_string == NULL && defined == B_TRUE) { xyerror(D_DECL_PARMNAME, "probe %s formal %s " "parameter lacks name: param #%d\n", pname, desc, i + 1); } } if (v != 0 && plist->dn_list != NULL) { xyerror(D_DECL_FUNCVOID, "void must be sole parameter in " "probe %s %s prototype\n", pname, desc); } if (i > UINT8_MAX) { xyerror(D_PROV_PRARGLEN, "probe %s %s prototype exceeds %u " "parameters: %d params used\n", pname, desc, UINT8_MAX, i); } return (v ? 0 : i); /* return zero if sole parameter is 'void' */}dt_node_t *dt_node_probe(char *s, dt_node_t *nargs, dt_node_t *xargs){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; int nargc, xargc; dt_node_t *dnp; char *name; name = alloca(strlen(s) + 1); (void) strcpy(name, s); (void) strhyphenate(name); free(s); if (strchr(name, '`') != NULL) { xyerror(D_PROV_BADNAME, "probe name may not " "contain scoping operator: %s\n", name); } if (strlen(name) >= DTRACE_NAMELEN) { xyerror(D_PROV_BADNAME, "probe name may not exceed %d " "characters: %s\n", DTRACE_NAMELEN - 1, name); } dnp = dt_node_alloc(DT_NODE_PROBE); dnp->dn_ident = dt_ident_create(name, DT_IDENT_PROBE, 0, 0, _dtrace_defattr, 0, &dt_idops_probe, (void *)CTF_ERR, dtp->dt_gen); nargc = dt_node_probe_prototype(name, "input", nargs, nargs, B_FALSE); xargc = dt_node_probe_prototype(name, "output", xargs, nargs, B_TRUE); if (dnp->dn_ident == NULL || (dnp->dn_ident->di_data = dt_probe_create(dnp->dn_ident, nargs, nargc, xargs, xargc)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); return (dnp);}dt_node_t *dt_node_provider(char *name, dt_node_t *probes){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *dnp, *pnp; dt_provider_t *pvp; dnp = dt_node_alloc(DT_NODE_PROVIDER); dnp->dn_string = name; dnp->dn_list = probes; if (!(dtp->dt_cflags & DTRACE_C_PRDEFS)) dnerror(dnp, D_PROV_NODEFS, "unexpected provider definition\n"); if (dt_provider_lookup(dtp, name) != NULL) dnerror(dnp, D_PROV_EXISTS, "provider redeclared: %s\n", name); if (strchr(name, '`') != NULL) { dnerror(dnp, D_PROV_BADNAME, "provider name may not " "contain scoping operator: %s\n", name); } if (strlen(name) >= DTRACE_PROVNAMELEN) { dnerror(dnp, D_PROV_BADNAME, "provider name may not exceed %d " "characters: %s\n", DTRACE_PROVNAMELEN - 1, name); } if ((pvp = dt_provider_create(dtp, dnp->dn_string)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); /* * Store all parse nodes created since we consumed the DT_KEY_PROVIDER * token with the provider and then restore our lexing state to CLAUSE. */ pvp->pv_nodes = yypcb->pcb_list; yybegin(YYS_CLAUSE); for (pnp = probes; pnp != NULL; pnp = pnp->dn_list) { if (dt_idhash_lookup(pvp->pv_probes, pnp->dn_ident->di_name)) { dnerror(pnp, D_PROV_PREXISTS, "probe redeclared: %s\n", pnp->dn_ident->di_name); } dt_idhash_xinsert(pvp->pv_probes, pnp->dn_ident); pnp->dn_ident = NULL; /* ident is now in idhash */ } return (dt_node_cook(dnp, DT_IDFLG_REF));}dt_node_t *dt_node_program(dt_node_t *lnp){ dt_node_t *dnp = dt_node_alloc(DT_NODE_PROG); dnp->dn_list = lnp; return (dnp);}/* * This function provides the underlying implementation of cooking an * identifier given its node, a hash of dynamic identifiers, an identifier * kind, and a boolean flag indicating whether we are allowed to instantiate * a new identifier if the string is not found. This function is either * called from dt_cook_ident(), below, or directly by the various cooking * routines that are allowed to instantiate identifiers (e.g. op2 TOK_ASGN). */static voiddt_xcook_i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -