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 + -
显示快捷键?