dt_decl.c

来自「Sun Solaris 10 中的 DTrace 组件的源代码。请参看: htt」· C语言 代码 · 共 1,055 行 · 第 1/2 页

C
1,055
字号
		dtt.dtt_type = ctf_add_integer(dsp->ds_ctfp,		    CTF_ADD_NONROOT, ctf_type_name(dtt.dtt_ctfp,		    dtt.dtt_type, n, sizeof (n)), &cte);		if (dtt.dtt_type == CTF_ERR ||		    ctf_update(dsp->ds_ctfp) == CTF_ERR) {			xyerror(D_UNKNOWN, "failed to create type for "			    "member '%s': %s\n", idname,			    ctf_errmsg(ctf_errno(dsp->ds_ctfp)));		}		dtt.dtt_ctfp = dsp->ds_ctfp;		dt_node_free(dnp);	}	/*	 * If the member type is not defined in the same CTF container as the	 * one associated with the current scope (i.e. the container for the	 * struct or union itself) or its parent, copy the member type into	 * this container and reset dtt to refer to the copied type.	 */	if (dtt.dtt_ctfp != dsp->ds_ctfp &&	    dtt.dtt_ctfp != ctf_parent_file(dsp->ds_ctfp)) {		dtt.dtt_type = ctf_add_type(dsp->ds_ctfp,		    dtt.dtt_ctfp, dtt.dtt_type);		dtt.dtt_ctfp = dsp->ds_ctfp;		if (dtt.dtt_type == CTF_ERR ||		    ctf_update(dtt.dtt_ctfp) == CTF_ERR) {			xyerror(D_UNKNOWN, "failed to copy type of '%s': %s\n",			    idname, ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));		}	}	if (ctf_add_member(dsp->ds_ctfp, dsp->ds_type,	    ident, dtt.dtt_type) == CTF_ERR) {		xyerror(D_UNKNOWN, "failed to define member '%s': %s\n",		    idname, ctf_errmsg(ctf_errno(dsp->ds_ctfp)));	}done:	free(ident);	yypcb->pcb_dstack.ds_ident = NULL;	dt_decl_reset();}/*ARGSUSED*/static intdt_decl_hasmembers(const char *name, int value, void *private){	return (1); /* abort search and return true if a member exists */}dt_decl_t *dt_decl_enum(char *name){	dt_decl_t *ddp = dt_decl_spec(CTF_K_ENUM, name);	char n[DT_TYPE_NAMELEN];	ctf_file_t *ctfp;	ctf_id_t type;	uint_t flag;	if (yypcb->pcb_idepth != 0)		ctfp = yypcb->pcb_hdl->dt_cdefs->dm_ctfp;	else		ctfp = yypcb->pcb_hdl->dt_ddefs->dm_ctfp;	if (yypcb->pcb_dstack.ds_next != NULL)		flag = CTF_ADD_NONROOT;	else		flag = CTF_ADD_ROOT;	(void) snprintf(n, sizeof (n), "enum %s", name ? name : "(anon)");	if (name != NULL && (type = ctf_lookup_by_name(ctfp, n)) != CTF_ERR) {		if (ctf_enum_iter(ctfp, type, dt_decl_hasmembers, NULL))			xyerror(D_DECL_TYPERED, "type redeclared: %s\n", n);	} else if ((type = ctf_add_enum(ctfp, flag, name)) == CTF_ERR) {		xyerror(D_UNKNOWN, "failed to define %s: %s\n",		    n, ctf_errmsg(ctf_errno(ctfp)));	}	ddp->dd_ctfp = ctfp;	ddp->dd_type = type;	dt_scope_push(ctfp, type);	return (ddp);}voiddt_decl_enumerator(char *s, dt_node_t *dnp){	dt_scope_t *dsp = yypcb->pcb_dstack.ds_next;	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_idnode_t *inp;	dt_ident_t *idp;	char *name;	int value;	name = alloca(strlen(s) + 1);	(void) strcpy(name, s);	free(s);	if (dsp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOSCOPE);	assert(dsp->ds_decl->dd_kind == CTF_K_ENUM);	value = dsp->ds_enumval + 1; /* default is previous value plus one */	if (strchr(name, '`') != NULL) {		xyerror(D_DECL_SCOPE, "D scoping operator may not be used in "		    "an enumerator name (%s)\n", name);	}	/*	 * If the enumerator is being assigned a value, cook and check the node	 * and then free it after we get the value.  We also permit references	 * to identifiers which are previously defined enumerators in the type.	 */	if (dnp != NULL) {		if (dnp->dn_kind != DT_NODE_IDENT || ctf_enum_value(		    dsp->ds_ctfp, dsp->ds_type, dnp->dn_string, &value) != 0) {			dnp = dt_node_cook(dnp, DT_IDFLG_REF);			if (dnp->dn_kind != DT_NODE_INT) {				xyerror(D_DECL_ENCONST, "enumerator '%s' must "				    "be assigned to an integral constant "				    "expression\n", name);			}			if ((intmax_t)dnp->dn_value > INT_MAX ||			    (intmax_t)dnp->dn_value < INT_MIN) {				xyerror(D_DECL_ENOFLOW, "enumerator '%s' value "				    "overflows INT_MAX (%d)\n", name, INT_MAX);			}			value = (int)dnp->dn_value;		}		dt_node_free(dnp);	}	if (ctf_add_enumerator(dsp->ds_ctfp, dsp->ds_type,	    name, value) == CTF_ERR || ctf_update(dsp->ds_ctfp) == CTF_ERR) {		xyerror(D_UNKNOWN, "failed to define enumerator '%s': %s\n",		    name, ctf_errmsg(ctf_errno(dsp->ds_ctfp)));	}	dsp->ds_enumval = value; /* save most recent value */	/*	 * If the enumerator name matches an identifier in the global scope,	 * flag this as an error.  We only do this for "D" enumerators to	 * prevent "C" header file enumerators from conflicting with the ever-	 * growing list of D built-in global variables and inlines.  If a "C"	 * enumerator conflicts with a global identifier, we add the enumerator	 * but do not insert a corresponding inline (i.e. the D variable wins).	 */	if (dt_idhash_lookup(dtp->dt_globals, name) != NULL) {		if (dsp->ds_ctfp == dtp->dt_ddefs->dm_ctfp) {			xyerror(D_DECL_IDRED,			    "identifier redeclared: %s\n", name);		} else			return;	}	dt_dprintf("add global enumerator %s = %d\n", name, value);	idp = dt_idhash_insert(dtp->dt_globals, name, DT_IDENT_ENUM,	    DT_IDFLG_INLINE | DT_IDFLG_REF, 0, _dtrace_defattr, 0,	    &dt_idops_inline, NULL, dtp->dt_gen);	if (idp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	yyintprefix = 0;	yyintsuffix[0] = '\0';	yyintdecimal = 0;	dnp = dt_node_int(value);	dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);	if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	/*	 * Remove the INT node from the node allocation list and store it in	 * din_list and din_root so it persists with and is freed by the ident.	 */	assert(yypcb->pcb_list == dnp);	yypcb->pcb_list = dnp->dn_link;	dnp->dn_link = NULL;	inp->din_list = dnp;	inp->din_root = dnp;	idp->di_data = inp;	idp->di_ctfp = dsp->ds_ctfp;	idp->di_type = dsp->ds_type;}/* * Look up the type corresponding to the specified decl stack.  The scoping of * the underlying type names is handled by dt_type_lookup().  We build up the * name from the specified string and prefixes and then lookup the type.  If * we fail, an errmsg is saved and the caller must abort with EDT_COMPILER. */intdt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip){	dtrace_hdl_t *dtp = yypcb->pcb_hdl;	dt_module_t *dmp;	ctf_arinfo_t r;	ctf_id_t type;	char n[DT_TYPE_NAMELEN];	uint_t flag;	char *name;	int rv;	/*	 * Based on our current #include depth and decl stack depth, determine	 * which dynamic CTF module and scope to use when adding any new types.	 */	dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;	flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;	/*	 * If we have already cached a CTF type for this decl, then we just	 * return the type information for the cached type.	 */	if (ddp->dd_ctfp != NULL &&	    (dmp = dt_module_lookup_by_ctf(dtp, ddp->dd_ctfp)) != NULL) {		tip->dtt_object = dmp->dm_name;		tip->dtt_ctfp = ddp->dd_ctfp;		tip->dtt_type = ddp->dd_type;		return (0);	}	/*	 * Currently CTF treats all function pointers identically.  We cache a	 * representative ID of kind CTF_K_FUNCTION and just return that type.	 * If we want to support full function declarations, dd_next refers to	 * the declaration of the function return type, and the parameter list	 * should be parsed and hung off a new pointer inside of this decl.	 */	if (ddp->dd_kind == CTF_K_FUNCTION) {		tip->dtt_object = dtp->dt_ddefs->dm_name;		tip->dtt_ctfp = DT_FUNC_CTFP(dtp);		tip->dtt_type = DT_FUNC_TYPE(dtp);		return (0);	}	/*	 * If the decl is a pointer, resolve the rest of the stack by calling	 * dt_decl_type() recursively and then compute a pointer to the result.	 * Similar to the code above, we return a cached id for function ptrs.	 */	if (ddp->dd_kind == CTF_K_POINTER) {		if (ddp->dd_next->dd_kind == CTF_K_FUNCTION) {			tip->dtt_object = dtp->dt_ddefs->dm_name;			tip->dtt_ctfp = DT_FPTR_CTFP(dtp);			tip->dtt_type = DT_FPTR_TYPE(dtp);			return (0);		}		if ((rv = dt_decl_type(ddp->dd_next, tip)) == 0 &&		    (rv = dt_type_pointer(tip)) != 0) {			xywarn(D_UNKNOWN, "cannot find type: %s*\n",			    dt_type_name(tip->dtt_ctfp, tip->dtt_type,			    n, sizeof (n)));		}		return (rv);	}	/*	 * If the decl is an array, we must find the base type and then call	 * dt_decl_type() recursively and then build an array of the result.	 * The C and D multi-dimensional array syntax requires that consecutive	 * array declarations be processed from right-to-left (i.e. top-down	 * from the perspective of the declaration stack).  For example, an	 * array declaration such as int x[3][5] is stored on the stack as:	 *	 * (bottom) NULL <- ( INT "int" ) <- ( ARR [3] ) <- ( ARR [5] ) (top)	 *	 * but means that x is declared to be an array of 3 objects each of	 * which is an array of 5 integers, or in CTF representation:	 *	 * type T1:( content=int, nelems=5 ) type T2:( content=T1, nelems=3 )	 *	 * For more details, refer to K&R[5.7] and ISO C 6.5.2.1.  Rather than	 * overcomplicate the implementation of dt_decl_type(), we push array	 * declarations down into the stack in dt_decl_array(), above, so that	 * by the time dt_decl_type() is called, the decl stack looks like:	 *	 * (bottom) NULL <- ( INT "int" ) <- ( ARR [5] ) <- ( ARR [3] ) (top)	 *	 * which permits a straightforward recursive descent of the decl stack	 * to build the corresponding CTF type tree in the appropriate order.	 */	if (ddp->dd_kind == CTF_K_ARRAY) {		/*		 * If the array decl has a parameter list associated with it,		 * this is an associative array declaration: return <DYN>.		 */		if (ddp->dd_node != NULL &&		    ddp->dd_node->dn_kind == DT_NODE_TYPE) {			tip->dtt_object = dtp->dt_ddefs->dm_name;			tip->dtt_ctfp = DT_DYN_CTFP(dtp);			tip->dtt_type = DT_DYN_TYPE(dtp);			return (0);		}		if ((rv = dt_decl_type(ddp->dd_next, tip)) != 0)			return (rv);		/*		 * If the array base type 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 (tip->dtt_ctfp != dmp->dm_ctfp &&		    tip->dtt_ctfp != ctf_parent_file(dmp->dm_ctfp)) {			tip->dtt_type = ctf_add_type(dmp->dm_ctfp,			    tip->dtt_ctfp, tip->dtt_type);			tip->dtt_ctfp = dmp->dm_ctfp;			if (tip->dtt_type == CTF_ERR ||			    ctf_update(tip->dtt_ctfp) == CTF_ERR) {				xywarn(D_UNKNOWN, "failed to copy type: %s\n",				    ctf_errmsg(ctf_errno(tip->dtt_ctfp)));				return (-1);			}		}		/*		 * The array index type is irrelevant in C and D: just set it		 * to "long" for all array types that we create on-the-fly.		 */		r.ctr_contents = tip->dtt_type;		r.ctr_index = ctf_lookup_by_name(tip->dtt_ctfp, "long");		r.ctr_nelems = ddp->dd_node ?		    (uint_t)ddp->dd_node->dn_value : 0;		tip->dtt_object = dmp->dm_name;		tip->dtt_ctfp = dmp->dm_ctfp;		tip->dtt_type = ctf_add_array(dmp->dm_ctfp, CTF_ADD_ROOT, &r);		if (tip->dtt_type == CTF_ERR ||		    ctf_update(tip->dtt_ctfp) == CTF_ERR) {			xywarn(D_UNKNOWN, "failed to create array type: %s\n",			    ctf_errmsg(ctf_errno(tip->dtt_ctfp)));			return (-1);		}		return (0);	}	/*	 * Allocate space for the type name and enough space for the maximum	 * additional text ("unsigned long long \0" requires 20 more bytes).	 */	name = alloca(ddp->dd_name ? strlen(ddp->dd_name) + 20 : 20);	name[0] = '\0';	switch (ddp->dd_kind) {	case CTF_K_INTEGER:	case CTF_K_FLOAT:		if (ddp->dd_attr & DT_DA_SIGNED)			(void) strcat(name, "signed ");		if (ddp->dd_attr & DT_DA_UNSIGNED)			(void) strcat(name, "unsigned ");		if (ddp->dd_attr & DT_DA_SHORT)			(void) strcat(name, "short ");		if (ddp->dd_attr & DT_DA_LONG)			(void) strcat(name, "long ");		if (ddp->dd_attr & DT_DA_LONGLONG)			(void) strcat(name, "long long ");		if (ddp->dd_attr == 0 && ddp->dd_name == NULL)			(void) strcat(name, "int");		break;	case CTF_K_STRUCT:		(void) strcpy(name, "struct ");		break;	case CTF_K_UNION:		(void) strcpy(name, "union ");		break;	case CTF_K_ENUM:		(void) strcpy(name, "enum ");		break;	case CTF_K_TYPEDEF:		break;	default:		xywarn(D_UNKNOWN, "internal error -- "		    "bad decl kind %u\n", ddp->dd_kind);		return (-1);	}	/*	 * Add dd_name unless a short, long, or long long is explicitly	 * suffixed by int.  We use the C/CTF canonical names for integers.	 */	if (ddp->dd_name != NULL && (ddp->dd_kind != CTF_K_INTEGER ||	    (ddp->dd_attr & (DT_DA_SHORT | DT_DA_LONG | DT_DA_LONGLONG)) == 0))		(void) strcat(name, ddp->dd_name);	/*	 * Lookup the type.  If we find it, we're done.  Otherwise create a	 * forward tag for the type if it is a struct, union, or enum.  If	 * we can't find it and we can't create a tag, return failure.	 */	if ((rv = dt_type_lookup(name, tip)) == 0)		return (rv);	switch (ddp->dd_kind) {	case CTF_K_STRUCT:		type = ctf_add_struct(dmp->dm_ctfp, flag, ddp->dd_name);		break;	case CTF_K_UNION:		type = ctf_add_union(dmp->dm_ctfp, flag, ddp->dd_name);		break;	case CTF_K_ENUM:		type = ctf_add_enum(dmp->dm_ctfp, flag, ddp->dd_name);		break;	default:		xywarn(D_UNKNOWN, "failed to resolve type %s: %s\n", name,		    dtrace_errmsg(dtp, dtrace_errno(dtp)));		return (rv);	}	if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {		xywarn(D_UNKNOWN, "failed to add forward tag for %s: %s\n",		    name, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));		return (-1);	}	ddp->dd_ctfp = dmp->dm_ctfp;	ddp->dd_type = type;	tip->dtt_object = dmp->dm_name;	tip->dtt_ctfp = dmp->dm_ctfp;	tip->dtt_type = type;	return (0);}voiddt_scope_create(dt_scope_t *dsp){	dsp->ds_decl = NULL;	dsp->ds_next = NULL;	dsp->ds_ident = NULL;	dsp->ds_ctfp = NULL;	dsp->ds_type = CTF_ERR;	dsp->ds_class = DT_DC_DEFAULT;	dsp->ds_enumval = -1;}voiddt_scope_destroy(dt_scope_t *dsp){	dt_scope_t *nsp;	for (; dsp != NULL; dsp = nsp) {		dt_decl_free(dsp->ds_decl);		free(dsp->ds_ident);		nsp = dsp->ds_next;		if (dsp != &yypcb->pcb_dstack)			free(dsp);	}}voiddt_scope_push(ctf_file_t *ctfp, ctf_id_t type){	dt_scope_t *rsp = &yypcb->pcb_dstack;	dt_scope_t *dsp = malloc(sizeof (dt_scope_t));	if (dsp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	dsp->ds_decl = rsp->ds_decl;	dsp->ds_next = rsp->ds_next;	dsp->ds_ident = rsp->ds_ident;	dsp->ds_ctfp = ctfp;	dsp->ds_type = type;	dsp->ds_class = rsp->ds_class;	dsp->ds_enumval = rsp->ds_enumval;	dt_scope_create(rsp);	rsp->ds_next = dsp;}dt_decl_t *dt_scope_pop(void){	dt_scope_t *rsp = &yypcb->pcb_dstack;	dt_scope_t *dsp = rsp->ds_next;	if (dsp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOSCOPE);	if (dsp->ds_ctfp != NULL && ctf_update(dsp->ds_ctfp) == CTF_ERR) {		xyerror(D_UNKNOWN, "failed to update type definitions: %s\n",		    ctf_errmsg(ctf_errno(dsp->ds_ctfp)));	}	dt_decl_free(rsp->ds_decl);	free(rsp->ds_ident);	rsp->ds_decl = dsp->ds_decl;	rsp->ds_next = dsp->ds_next;	rsp->ds_ident = dsp->ds_ident;	rsp->ds_ctfp = dsp->ds_ctfp;	rsp->ds_type = dsp->ds_type;	rsp->ds_class = dsp->ds_class;	rsp->ds_enumval = dsp->ds_enumval;	free(dsp);	return (rsp->ds_decl);}

⌨️ 快捷键说明

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