dt_decl.c

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

C
1,055
字号
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)dt_decl.c	1.3	04/11/13 SMI"#include <strings.h>#include <stdlib.h>#include <limits.h>#include <alloca.h>#include <assert.h>#include <dt_decl.h>#include <dt_parser.h>#include <dt_module.h>#include <dt_impl.h>static dt_decl_t *dt_decl_check(dt_decl_t *ddp){	if (ddp->dd_kind == CTF_K_UNKNOWN)		return (ddp); /* nothing to check if the type is not yet set */	if (ddp->dd_name != NULL && strcmp(ddp->dd_name, "char") == 0 &&	    (ddp->dd_attr & (DT_DA_SHORT | DT_DA_LONG | DT_DA_LONGLONG))) {		xyerror(D_DECL_CHARATTR, "invalid type declaration: short and "		    "long may not be used with char type\n");	}	if (ddp->dd_name != NULL && strcmp(ddp->dd_name, "void") == 0 &&	    (ddp->dd_attr & (DT_DA_SHORT | DT_DA_LONG | DT_DA_LONGLONG |	    (DT_DA_SIGNED | DT_DA_UNSIGNED)))) {		xyerror(D_DECL_VOIDATTR, "invalid type declaration: attributes "		    "may not be used with void type\n");	}	if (ddp->dd_kind != CTF_K_INTEGER &&	    (ddp->dd_attr & (DT_DA_SIGNED | DT_DA_UNSIGNED))) {		xyerror(D_DECL_SIGNINT, "invalid type declaration: signed and "		    "unsigned may only be used with integer type\n");	}	if (ddp->dd_kind != CTF_K_INTEGER && ddp->dd_kind != CTF_K_FLOAT &&	    (ddp->dd_attr & (DT_DA_LONG | DT_DA_LONGLONG))) {		xyerror(D_DECL_LONGINT, "invalid type declaration: long and "		    "long long may only be used with integer or "		    "floating-point type\n");	}	return (ddp);}dt_decl_t *dt_decl_alloc(ushort_t kind, char *name){	dt_decl_t *ddp = malloc(sizeof (dt_decl_t));	if (ddp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);	ddp->dd_kind = kind;	ddp->dd_attr = 0;	ddp->dd_ctfp = NULL;	ddp->dd_type = CTF_ERR;	ddp->dd_name = name;	ddp->dd_node = NULL;	ddp->dd_next = NULL;	return (ddp);}voiddt_decl_free(dt_decl_t *ddp){	dt_decl_t *ndp;	for (; ddp != NULL; ddp = ndp) {		ndp = ddp->dd_next;		free(ddp->dd_name);		dt_node_list_free(&ddp->dd_node);		free(ddp);	}}voiddt_decl_reset(void){	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_decl_t *ddp = dsp->ds_decl;	while (ddp->dd_next != NULL) {		dsp->ds_decl = ddp->dd_next;		ddp->dd_next = NULL;		dt_decl_free(ddp);		ddp = dsp->ds_decl;	}}dt_decl_t *dt_decl_push(dt_decl_t *ddp){	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_decl_t *top = dsp->ds_decl;	if (top != NULL &&	    top->dd_kind == CTF_K_UNKNOWN && top->dd_name == NULL) {		top->dd_kind = CTF_K_INTEGER;		(void) dt_decl_check(top);	}	assert(ddp->dd_next == NULL);	ddp->dd_next = top;	dsp->ds_decl = ddp;	return (ddp);}dt_decl_t *dt_decl_pop(void){	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_decl_t *ddp = dt_decl_top();	dsp->ds_decl = NULL;	free(dsp->ds_ident);	dsp->ds_ident = NULL;	dsp->ds_ctfp = NULL;	dsp->ds_type = CTF_ERR;	dsp->ds_class = DT_DC_DEFAULT;	dsp->ds_enumval = -1;	return (ddp);}dt_decl_t *dt_decl_pop_param(char **idp){	dt_scope_t *dsp = &yypcb->pcb_dstack;	if (dsp->ds_class != DT_DC_DEFAULT && dsp->ds_class != DT_DC_REGISTER) {		xyerror(D_DECL_PARMCLASS, "inappropriate storage class "		    "for function or associative array parameter\n");	}	if (idp != NULL && dt_decl_top() != NULL) {		*idp = dsp->ds_ident;		dsp->ds_ident = NULL;	}	return (dt_decl_pop());}dt_decl_t *dt_decl_top(void){	dt_decl_t *ddp = yypcb->pcb_dstack.ds_decl;	if (ddp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NODECL);	if (ddp->dd_kind == CTF_K_UNKNOWN && ddp->dd_name == NULL) {		ddp->dd_kind = CTF_K_INTEGER;		(void) dt_decl_check(ddp);	}	return (ddp);}dt_decl_t *dt_decl_ident(char *name){	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_decl_t *ddp = dsp->ds_decl;	if (dsp->ds_ident != NULL) {		free(name);		xyerror(D_DECL_IDENT, "old-style declaration or "		    "incorrect type specified\n");	}	dsp->ds_ident = name;	if (ddp == NULL)		ddp = dt_decl_push(dt_decl_alloc(CTF_K_UNKNOWN, NULL));	return (ddp);}voiddt_decl_class(dt_dclass_t class){	dt_scope_t *dsp = &yypcb->pcb_dstack;	if (dsp->ds_class != DT_DC_DEFAULT) {		xyerror(D_DECL_CLASS, "only one storage class allowed "		    "in a declaration\n");	}	dsp->ds_class = class;}/* * Set the kind and name of the current declaration.  If none is allocated, * make a new decl and push it on to the top of our stack.  If the name or kind * is already set for the current decl, then we need to fail this declaration. * This can occur because too many types were given (e.g. "int int"), etc. */dt_decl_t *dt_decl_spec(ushort_t kind, char *name){	dt_decl_t *ddp = yypcb->pcb_dstack.ds_decl;	if (ddp == NULL)		return (dt_decl_push(dt_decl_alloc(kind, name)));	/*	 * If we already have a type name specified and we see another type	 * name, this is an error if the declaration is a typedef.  If the	 * declaration is not a typedef, then the user may be trying to declare	 * a variable whose name has been returned by lex as a TNAME token:	 * call dt_decl_ident() as if the grammar's IDENT rule was matched.	 */	if (ddp->dd_name != NULL && kind == CTF_K_TYPEDEF) {		if (yypcb->pcb_dstack.ds_class != DT_DC_TYPEDEF)			return (dt_decl_ident(name));		xyerror(D_DECL_IDRED, "identifier redeclared: %s\n", name);	}	if (ddp->dd_name != NULL || ddp->dd_kind != CTF_K_UNKNOWN)		xyerror(D_DECL_COMBO, "invalid type combination\n");	ddp->dd_kind = kind;	ddp->dd_name = name;	if (name != NULL && strchr(name, '`') != NULL) {		xyerror(D_DECL_SCOPE, "D scoping operator may not be used "		    "in a type name\n");	}	return (dt_decl_check(ddp));}dt_decl_t *dt_decl_attr(ushort_t attr){	dt_decl_t *ddp = yypcb->pcb_dstack.ds_decl;	if (ddp == NULL) {		ddp = dt_decl_push(dt_decl_alloc(CTF_K_UNKNOWN, NULL));		ddp->dd_attr = attr;		return (ddp);	}	if (attr == DT_DA_LONG && (ddp->dd_attr & DT_DA_LONG)) {		ddp->dd_attr &= ~DT_DA_LONG;		attr = DT_DA_LONGLONG;	}	ddp->dd_attr |= attr;	return (dt_decl_check(ddp));}dt_decl_t *dt_decl_array(dt_node_t *dnp){	dt_decl_t *ddp = dt_decl_push(dt_decl_alloc(CTF_K_ARRAY, NULL));	dt_scope_t *dsp = &yypcb->pcb_dstack;	dt_decl_t *ndp = ddp;	/*	 * After pushing the array on to the decl stack, scan ahead for multi-	 * dimensional array declarations and push the current decl to the	 * bottom to match the resulting CTF type tree and data layout.  Refer	 * to the comments in dt_decl_type() and ISO C 6.5.2.1 for more info.	 */	while (ndp->dd_next != NULL && ndp->dd_next->dd_kind == CTF_K_ARRAY)		ndp = ndp->dd_next; /* skip to bottom-most array declaration */	if (ndp != ddp) {		if (dnp != NULL && dnp->dn_kind == DT_NODE_TYPE) {			xyerror(D_DECL_DYNOBJ,			    "cannot declare array of associative arrays\n");		}		dsp->ds_decl = ddp->dd_next;		ddp->dd_next = ndp->dd_next;		ndp->dd_next = ddp;	}	if (ddp->dd_next->dd_name != NULL &&	    strcmp(ddp->dd_next->dd_name, "void") == 0)		xyerror(D_DECL_VOIDOBJ, "cannot declare array of void\n");	if (dnp == NULL)		return (ddp); /* no array dimension or tuple signature */	if (dnp->dn_kind == DT_NODE_TYPE) {		char n[DT_TYPE_NAMELEN];		int i = 1;		for (ddp->dd_node = dnp; dnp != NULL; dnp = dnp->dn_list, i++) {			if (dnp->dn_type == CTF_ERR) {				xyerror(D_DECL_ARRVA, "array tuples may not "				    "use variable-length argument lists\n");			}			if (dt_node_is_dynamic(dnp) || dt_node_is_void(dnp)) {				xyerror(D_DECL_ARRTYPE, "%s type may not be "				    "used in array tuples: key #%d\n",				    dt_node_type_name(dnp, n, sizeof (n)), i);			}		}	} else {		dnp = ddp->dd_node = dt_node_cook(dnp, DT_IDFLG_REF);		if (dt_node_is_posconst(dnp) == 0) {			xyerror(D_DECL_ARRSUB, "positive integral constant "			    "expression or tuple signature expected as "			    "array declaration subscript\n");		}		if (dnp->dn_value > UINT_MAX)			xyerror(D_DECL_ARRBIG, "array dimension too big\n");	}	return (ddp);}/* * When a function is declared, we need to fudge the decl stack a bit if the * declaration uses the function pointer (*)() syntax.  In this case, the * dt_decl_func() call occurs *after* the dt_decl_ptr() call, even though the * resulting type is "pointer to function".  To make the pointer land on top, * we check to see if 'pdp' is non-NULL and a pointer.  If it is, we search * backward for a decl tagged with DT_DA_PAREN, and if one is found, the func * decl is inserted behind this node in the decl list instead of at the top. * In all cases, the func decl's dd_next pointer is set to the decl chain * for the function's return type and the function parameter list is discarded. */dt_decl_t *dt_decl_func(dt_decl_t *pdp, dt_node_t *dnp){	dt_decl_t *ddp = dt_decl_alloc(CTF_K_FUNCTION, NULL);	char n[DT_TYPE_NAMELEN];	int i = 1, v = 0;	for (ddp->dd_node = dnp; dnp != NULL; dnp = dnp->dn_list, i++) {		if (dt_node_is_dynamic(dnp)) {			xyerror(D_DECL_FUNCTYPE, "%s type may not be "			    "used in function prototypes: arg #%d\n",			    dt_node_type_name(dnp, n, sizeof (n)), i);		}		if (dnp->dn_type != CTF_ERR)			v += dt_node_is_void(dnp);	}	if (v != 0 && ddp->dd_node->dn_list != NULL)		xyerror(D_DECL_FUNCVOID, "void must be sole parameter\n");	if (pdp == NULL || pdp->dd_kind != CTF_K_POINTER)		return (dt_decl_push(ddp));	while (pdp->dd_next != NULL && !(pdp->dd_next->dd_attr & DT_DA_PAREN))		pdp = pdp->dd_next;	if (pdp->dd_next == NULL)		return (dt_decl_push(ddp));	ddp->dd_next = pdp->dd_next;	pdp->dd_next = ddp;	return (pdp);}dt_decl_t *dt_decl_ptr(void){	return (dt_decl_push(dt_decl_alloc(CTF_K_POINTER, NULL)));}dt_decl_t *dt_decl_sou(uint_t kind, char *name){	dt_decl_t *ddp = dt_decl_spec(kind, 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), "%s %s",	    kind == CTF_K_STRUCT ? "struct" : "union",	    name == NULL ? "(anon)" : name);	if (name != NULL && (type = ctf_lookup_by_name(ctfp, n)) != CTF_ERR) {		if (ctf_type_size(ctfp, type) != 0)			xyerror(D_DECL_TYPERED, "type redeclared: %s\n", n);	} else {		if (kind == CTF_K_STRUCT)			type = ctf_add_struct(ctfp, flag, name);		else			type = ctf_add_union(ctfp, flag, name);		if (type == CTF_ERR || ctf_update(ctfp) == 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_member(dt_node_t *dnp){	dt_scope_t *dsp = yypcb->pcb_dstack.ds_next;	dt_decl_t *ddp = yypcb->pcb_dstack.ds_decl;	char *ident = yypcb->pcb_dstack.ds_ident;	const char *idname = ident ? ident : "(anon)";	char n[DT_TYPE_NAMELEN];	dtrace_typeinfo_t dtt;	ctf_encoding_t cte;	ctf_id_t base;	uint_t kind;	ssize_t size;	if (dsp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NOSCOPE);	if (ddp == NULL)		longjmp(yypcb->pcb_jmpbuf, EDT_NODECL);	if (dnp == NULL && ident == NULL)		xyerror(D_DECL_MNAME, "member declaration requires a name\n");	if (ddp->dd_kind == CTF_K_UNKNOWN && ddp->dd_name == NULL) {		ddp->dd_kind = CTF_K_INTEGER;		(void) dt_decl_check(ddp);	}	if (dt_decl_type(ddp, &dtt) != 0)		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);	if (ident != NULL && strchr(ident, '`') != NULL) {		xyerror(D_DECL_SCOPE, "D scoping operator may not be used "		    "in a member name (%s)\n", ident);	}	if (dtt.dtt_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) &&	    dtt.dtt_type == DT_DYN_TYPE(yypcb->pcb_hdl)) {		xyerror(D_DECL_DYNOBJ,		    "cannot have dynamic member: %s\n", ident);	}	base = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);	kind = ctf_type_kind(dtt.dtt_ctfp, base);	size = ctf_type_size(dtt.dtt_ctfp, base);	if (kind == CTF_K_FORWARD || ((kind == CTF_K_STRUCT ||	    kind == CTF_K_UNION) && size == 0)) {		xyerror(D_DECL_INCOMPLETE, "incomplete struct/union/enum %s: "		    "%s\n", dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,		    n, sizeof (n)), ident);	}	if (size == 0)		xyerror(D_DECL_VOIDOBJ, "cannot have void member: %s\n", ident);	/*	 * If a bit-field qualifier was part of the member declaration, create	 * a new integer type of the same name and attributes as the base type	 * and size equal to the specified number of bits.  We reset 'dtt' to	 * refer to this new bit-field type and continue on to add the member.	 */	if (dnp != NULL) {		dnp = dt_node_cook(dnp, DT_IDFLG_REF);		/*		 * A bit-field member with no declarator is permitted to have		 * size zero and indicates that no more fields are to be packed		 * into the current storage unit.  We ignore these directives		 * as the underlying ctf code currently does so for all fields.		 */		if (ident == NULL && dnp->dn_kind == DT_NODE_INT &&		    dnp->dn_value == 0) {			dt_node_free(dnp);			goto done;		}		if (dt_node_is_posconst(dnp) == 0) {			xyerror(D_DECL_BFCONST, "positive integral constant "			    "expression expected as bit-field size\n");		}		if (ctf_type_kind(dtt.dtt_ctfp, base) != CTF_K_INTEGER ||		    ctf_type_encoding(dtt.dtt_ctfp, base, &cte) == CTF_ERR ||		    IS_VOID(cte)) {			xyerror(D_DECL_BFTYPE, "invalid type for "			    "bit-field: %s\n", idname);		}		if (dnp->dn_value > cte.cte_bits) {			xyerror(D_DECL_BFSIZE, "bit-field too big "			    "for type: %s\n", idname);		}		cte.cte_offset = 0;		cte.cte_bits = (uint_t)dnp->dn_value;

⌨️ 快捷键说明

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