⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dt_parser.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
		    ctf_array_info(lfp, lbase, &r) == 0) {			lref = ctf_type_resolve(lfp, r.ctr_contents);		}	}	if (!rp_is_int) {		rbase = ctf_type_resolve(rfp, rp->dn_type);		rkind = ctf_type_kind(rfp, rbase);		if (rkind == CTF_K_POINTER) {			rref = ctf_type_resolve(rfp,			    ctf_type_reference(rfp, rbase));		} else if (rkind == CTF_K_ARRAY &&		    ctf_array_info(rfp, rbase, &r) == 0) {			rref = ctf_type_resolve(rfp, r.ctr_contents);		}	}	/*	 * We know that one or the other type may still be a zero-valued	 * integer constant.  To simplify the code below, set the integer	 * type variables equal to the non-integer types and proceed.	 */	if (lp_is_int) {		lbase = rbase;		lkind = rkind;		lref = rref;		lfp = rfp;	} else if (rp_is_int) {		rbase = lbase;		rkind = lkind;		rref = lref;		rfp = lfp;	}	lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e);	rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e);	/*	 * The types are compatible if both are pointers to the same type, or	 * if either pointer is a void pointer.  If they are compatible, set	 * tp to point to the more specific pointer type and return it.	 */	compat = (lkind == CTF_K_POINTER || lkind == CTF_K_ARRAY) &&	    (rkind == CTF_K_POINTER || rkind == CTF_K_ARRAY) &&	    (lp_is_void || rp_is_void || ctf_type_compat(lfp, lref, rfp, rref));	if (compat) {		if (fpp != NULL)			*fpp = rp_is_void ? lfp : rfp;		if (tp != NULL)			*tp = rp_is_void ? lbase : rbase;	}	return (compat);}/* * The rules for checking argument types against parameter types are described * in the ANSI-C spec (see K&R[A7.3.2] and K&R[A7.17]).  We use the same rule * set to determine whether associative array arguments match the prototype. */intdt_node_is_argcompat(const dt_node_t *lp, const dt_node_t *rp){	ctf_file_t *lfp = lp->dn_ctfp;	ctf_file_t *rfp = rp->dn_ctfp;	assert(lp->dn_flags & DT_NF_COOKED);	assert(rp->dn_flags & DT_NF_COOKED);	if (dt_node_is_integer(lp) && dt_node_is_integer(rp))		return (1); /* integer types are compatible */	if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp))		return (1); /* string types are compatible */	if (dt_node_is_stack(lp) && dt_node_is_stack(rp))		return (1); /* stack types are compatible */	switch (ctf_type_kind(lfp, ctf_type_resolve(lfp, lp->dn_type))) {	case CTF_K_FUNCTION:	case CTF_K_STRUCT:	case CTF_K_UNION:		return (ctf_type_compat(lfp, lp->dn_type, rfp, rp->dn_type));	default:		return (dt_node_is_ptrcompat(lp, rp, NULL, NULL));	}}/* * We provide dt_node_is_posconst() as a convenience routine for callers who * wish to verify that an argument is a positive non-zero integer constant. */intdt_node_is_posconst(const dt_node_t *dnp){	return (dnp->dn_kind == DT_NODE_INT && dnp->dn_value != 0 && (	    (dnp->dn_flags & DT_NF_SIGNED) == 0 || (int64_t)dnp->dn_value > 0));}intdt_node_is_actfunc(const dt_node_t *dnp){	return (dnp->dn_kind == DT_NODE_FUNC &&	    dnp->dn_ident->di_kind == DT_IDENT_ACTFUNC);}/* * The original rules for integer constant typing are described in K&R[A2.5.1]. * However, since we support long long, we instead use the rules from ISO C99 * clause 6.4.4.1 since that is where long longs are formally described.  The * rules require us to know whether the constant was specified in decimal or * in octal or hex, which we do by looking at our lexer's 'yyintdecimal' flag. * The type of an integer constant is the first of the corresponding list in * which its value can be represented: * * unsuffixed decimal:   int, long, long long * unsuffixed oct/hex:   int, unsigned int, long, unsigned long, *                       long long, unsigned long long * suffix [uU]:          unsigned int, unsigned long, unsigned long long * suffix [lL] decimal:  long, long long * suffix [lL] oct/hex:  long, unsigned long, long long, unsigned long long * suffix [uU][Ll]:      unsigned long, unsigned long long * suffix ll/LL decimal: long long * suffix ll/LL oct/hex: long long, unsigned long long * suffix [uU][ll/LL]:   unsigned long long * * Given that our lexer has already validated the suffixes by regexp matching, * there is an obvious way to concisely encode these rules: construct an array * of the types in the order int, unsigned int, long, unsigned long, long long, * unsigned long long.  Compute an integer array starting index based on the * suffix (e.g. none = 0, u = 1, ull = 5), and compute an increment based on * the specifier (dec/oct/hex) and suffix (u).  Then iterate from the starting * index to the end, advancing using the increment, and searching until we * find a limit that matches or we run out of choices (overflow).  To make it * even faster, we precompute the table of type information in dtrace_open(). */dt_node_t *dt_node_int(uintmax_t value){	dt_node_t *dnp = dt_node_alloc(DT_NODE_INT);	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	int n = (yyintdecimal | (yyintsuffix[0] == 'u')) + 1;	int i = 0;	const char *p;	char c;	dnp->dn_op = DT_TOK_INT;	dnp->dn_value = value;	for (p = yyintsuffix; (c = *p) != '\0'; p++) {		if (c == 'U' || c == 'u')			i += 1;		else if (c == 'L' || c == 'l')			i += 2;	}	for (; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i += n) {		if (value <= dtp->dt_ints[i].did_limit) {			dt_node_type_assign(dnp,			    dtp->dt_ints[i].did_ctfp,			    dtp->dt_ints[i].did_type);			/*			 * If a prefix character is present in macro text, add			 * in the corresponding operator node (see dt_lex.l).			 */			switch (yyintprefix) {			case '+':				return (dt_node_op1(DT_TOK_IPOS, dnp));			case '-':				return (dt_node_op1(DT_TOK_INEG, dnp));			default:				return (dnp);			}		}	}	xyerror(D_INT_OFLOW, "integer constant 0x%llx cannot be represented "	    "in any built-in integral type\n", (u_longlong_t)value);	/*NOTREACHED*/	return (NULL);		/* keep gcc happy */}dt_node_t *dt_node_string(char *string){	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_node_t *dnp;	if (string == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	dnp = dt_node_alloc(DT_NODE_STRING);	dnp->dn_op = DT_TOK_STRING;	dnp->dn_string = string;	dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));	return (dnp);}dt_node_t *dt_node_ident(char *name){	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_ident_t *idp;	dt_node_t *dnp;	if (name == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	/*	 * If the identifier is an inlined integer constant, then create an INT	 * node that is a clone of the inline parse tree node and return that	 * immediately, allowing this inline to be used in parsing contexts	 * that require constant expressions (e.g. scalar array sizes).	 */	if ((idp = dt_idhash_lookup(dtp->dt_globals, name)) != NULL &&	    (idp->di_flags & DT_IDFLG_INLINE)) {		dt_idnode_t *inp = idp->di_data;		if (inp->din_root->dn_kind == DT_NODE_INT) {			free(name);			dnp = dt_node_alloc(DT_NODE_INT);			dnp->dn_op = DT_TOK_INT;			dnp->dn_value = inp->din_root->dn_value;			dt_node_type_propagate(inp->din_root, dnp);			return (dnp);		}	}	dnp = dt_node_alloc(DT_NODE_IDENT);	dnp->dn_op = name[0] == '@' ? DT_TOK_AGG : DT_TOK_IDENT;	dnp->dn_string = name;	return (dnp);}/* * Create an empty node of type corresponding to the given declaration. * Explicit references to user types (C or D) are assigned the default * stability; references to other types are _dtrace_typattr (Private). */dt_node_t *dt_node_type(dt_decl_t *ddp){	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dtrace_typeinfo_t dtt;	dt_node_t *dnp;	char *name = NULL;	int err;	/*	 * If 'ddp' is NULL, we get a decl by popping the decl stack.  This	 * form of dt_node_type() is used by parameter rules in dt_grammar.y.	 */	if (ddp == NULL)		ddp = dt_decl_pop_param(&name);	err = dt_decl_type(ddp, &dtt);	dt_decl_free(ddp);	if (err != 0) {		free(name);		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);	}	dnp = dt_node_alloc(DT_NODE_TYPE);	dnp->dn_op = DT_TOK_IDENT;	dnp->dn_string = name;	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);	if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||	    dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)		dt_node_attr_assign(dnp, _dtrace_defattr);	else		dt_node_attr_assign(dnp, _dtrace_typattr);	return (dnp);}/* * Create a type node corresponding to a varargs (...) parameter by just * assigning it type CTF_ERR.  The decl processing code will handle this. */dt_node_t *dt_node_vatype(void){	dt_node_t *dnp = dt_node_alloc(DT_NODE_TYPE);	dnp->dn_op = DT_TOK_IDENT;	dnp->dn_ctfp = NULL;	dnp->dn_type = CTF_ERR;	dnp->dn_attr = _dtrace_defattr;	return (dnp);}/* * Instantiate a decl using the contents of the current declaration stack.  As * we do not currently permit decls to be initialized, this function currently * returns NULL and no parse node is created.  When this function is called, * the topmost scope's ds_ident pointer will be set to NULL (indicating no * init_declarator rule was matched) or will point to the identifier to use. */dt_node_t *dt_node_decl(void){	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_dclass_t class = dsp->ds_class;	dt_decl_t *ddp = dt_decl_top();	dt_module_t *dmp;	dtrace_typeinfo_t dtt;	ctf_id_t type;	char n1[DT_TYPE_NAMELEN];	char n2[DT_TYPE_NAMELEN];	if (dt_decl_type(ddp, &dtt) != 0)		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);	/*	 * If we have no declaration identifier, then this is either a spurious	 * declaration of an intrinsic type (e.g. "extern int;") or declaration	 * or redeclaration of a struct, union, or enum type or tag.	 */	if (dsp->ds_ident == NULL) {		if (ddp->dd_kind != CTF_K_STRUCT &&		    ddp->dd_kind != CTF_K_UNION && ddp->dd_kind != CTF_K_ENUM)			xyerror(D_DECL_USELESS, "useless declaration\n");		dt_dprintf("type %s added as id %ld\n", dt_type_name(		    ddp->dd_ctfp, ddp->dd_type, n1, sizeof (n1)), ddp->dd_type);		return (NULL);	}	if (strchr(dsp->ds_ident, '`') != NULL) {		xyerror(D_DECL_SCOPE, "D scoping operator may not be used in "		    "a declaration name (%s)\n", dsp->ds_ident);	}	/*	 * If we are nested inside of a C include file, add the declaration to	 * the C definition module; otherwise use the D definition module.	 */	if (yypcb->pcb_idepth != 0)		dmp = dtp->dt_cdefs;	else		dmp = dtp->dt_ddefs;	/*	 * If we see a global or static declaration of a function prototype,	 * treat this as equivalent to a D extern declaration.	 */	if (ctf_type_kind(dtt.dtt_ctfp, dtt.dtt_type) == CTF_K_FUNCTION &&	    (class == DT_DC_DEFAULT || class == DT_DC_STATIC))		class = DT_DC_EXTERN;	switch (class) {	case DT_DC_AUTO:	case DT_DC_REGISTER:	case DT_DC_STATIC:		xyerror(D_DECL_BADCLASS, "specified storage class not "		    "appropriate in D\n");		/*NOTREACHED*/	case DT_DC_EXTERN: {		dtrace_typeinfo_t ott;		dtrace_syminfo_t dts;		GElf_Sym sym;		int exists = dtrace_lookup_by_name(dtp,		    dmp->dm_name, dsp->ds_ident, &sym, &dts) == 0;		if (exists && (dtrace_symbol_type(dtp, &sym, &dts, &ott) != 0 ||		    ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type,		    ott.dtt_ctfp, ott.dtt_type) != 0)) {			xyerror(D_DECL_IDRED, "identifier redeclared: %s`%s\n"			    "\t current: %s\n\tprevious: %s\n",			    dmp->dm_name, dsp->ds_ident,			    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,				n1, sizeof (n1)),			    dt_type_name(ott.dtt_ctfp, ott.dtt_type,				n2, sizeof (n2)));		} else if (!exists && dt_module_extern(dtp, dmp,		    dsp->ds_ident, &dtt) == NULL) {			xyerror(D_UNKNOWN,			    "failed to extern %s: %s\n", dsp->ds_ident,			    dtrace_errmsg(dtp, dtrace_errno(dtp)));		} else {			dt_dprintf("extern %s`%s type=<%s>\n",			    dmp->dm_name, dsp->ds_ident,			    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,				n1, sizeof (n1)));		}		break;	}	case DT_DC_TYPEDEF:		/*		 * If the source type for the typedef is not defined in the		 * target container or its parent, copy the type to the target		 * container and reset dtt_ctfp and dtt_type to the copy.		 */		if (dtt.dtt_ctfp != dmp->dm_ctfp &&		    dtt.dtt_ctfp != ctf_parent_file(dmp->dm_ctfp)) {			dtt.dtt_type = ctf_add_type(dmp->dm_ctfp,			    dtt.dtt_ctfp, dtt.dtt_type);			dtt.dtt_ctfp = dmp->dm_ctfp;			if (dtt.dtt_type == CTF_ERR ||			    ctf_update(dtt.dtt_ctfp) == CTF_ERR) {				xyerror(D_UNKNOWN, "failed to copy typedef %s "				    "source type: %s\n", dsp->ds_ident,				    ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));			}		}		type = ctf_add_typedef(dmp->dm_ctfp,		    CTF_ADD_ROOT, dsp->ds_ident, dtt.dtt_type);		if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {			xyerror(D_UNKNOWN, "failed to typedef %s: %s\n",			    dsp->ds_ident, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));		}		dt_dprintf("typedef %s added as id %ld\n", dsp->ds_ident, type);		break;	default: {		ctf_encoding_t cte;		dt_idhash_t *dhp;		dt_ident_t *idp;		dt_node_t idn;		int assc, idkind;		uint_t id, kind;		ushort_t idflags;		switch (class) {		case DT_DC_THIS:			dhp = yypcb->pcb_locals;			idflags = DT_IDFLG_LOCAL;			break;		case DT_DC_SELF:			dhp = dtp->dt_tls;			idflags = DT_IDFLG_TLS;			break;		default:			dhp = dtp->dt_globals;			idflags = 0;			break;		}		if (ddp->dd_kind == CTF_K_ARRAY && ddp->dd_node == NULL) {			xyerror(D_DECL_ARRNULL,			    "array declaration requires array dimension or "			    "tuple signature: %s\n", dsp->ds_ident);		}		/*		 * Create a fake dt_node_t on the stack so we can determine the		 * type of the ident if it's defined.  We look it up in the		 * appropriate hash table (dhp) and cook it into the node (idn).		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -