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

📄 dt_printf.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
		return (dt_set_errno(dtp, EDT_DMISMATCH));	}	return (pfprint_estr(dtp, fp, format, pfd, &c, 1, normal));}/*ARGSUSED*/static intpfprint_pct(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	return (dt_printf(dtp, fp, "%%"));}static const char pfproto_xint[] = "char, short, int, long, or long long";static const char pfproto_csi[] = "char, short, or int";static const char pfproto_fp[] = "float, double, or long double";static const char pfproto_addr[] = "pointer or integer";static const char pfproto_cstr[] = "char [] or string (or use stringof)";static const char pfproto_wstr[] = "wchar_t []";/* * Printf format conversion dictionary.  This table should match the set of * conversions offered by printf(3C), as well as some additional extensions. * The second parameter is an ASCII string which is either an actual type * name we should look up (if pfcheck_type is specified), or just a descriptive * string of the types expected for use in error messages. */static const dt_pfconv_t _dtrace_conversions[] = {{ "a", "s", pfproto_addr, pfcheck_addr, pfprint_addr },{ "A", "s", pfproto_addr, pfcheck_addr, pfprint_uaddr },{ "c", "c", pfproto_csi, pfcheck_csi, pfprint_sint },{ "C", "s", pfproto_csi, pfcheck_csi, pfprint_echr },{ "d", "d", pfproto_xint, pfcheck_dint, pfprint_dint },{ "e", "e", pfproto_fp, pfcheck_fp, pfprint_fp },{ "E", "E", pfproto_fp, pfcheck_fp, pfprint_fp },{ "f", "f", pfproto_fp, pfcheck_fp, pfprint_fp },{ "g", "g", pfproto_fp, pfcheck_fp, pfprint_fp },{ "G", "G", pfproto_fp, pfcheck_fp, pfprint_fp },{ "hd", "d", "short", pfcheck_type, pfprint_sint },{ "hi", "i", "short", pfcheck_type, pfprint_sint },{ "ho", "o", "unsigned short", pfcheck_type, pfprint_uint },{ "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },{ "hx", "x", "short", pfcheck_xshort, pfprint_uint },{ "hX", "X", "short", pfcheck_xshort, pfprint_uint },{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },{ "k", "s", "stack", pfcheck_type, pfprint_stack },{ "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */{ "ld",	"d", "long", pfcheck_type, pfprint_sint },{ "li",	"i", "long", pfcheck_type, pfprint_sint },{ "lo",	"o", "unsigned long", pfcheck_type, pfprint_uint },{ "lu", "u", "unsigned long", pfcheck_type, pfprint_uint },{ "ls",	"ls", pfproto_wstr, pfcheck_wstr, pfprint_wstr },{ "lx",	"x", "long", pfcheck_xlong, pfprint_uint },{ "lX",	"X", "long", pfcheck_xlong, pfprint_uint },{ "lld", "d", "long long", pfcheck_type, pfprint_sint },{ "lli", "i", "long long", pfcheck_type, pfprint_sint },{ "llo", "o", "unsigned long long", pfcheck_type, pfprint_uint },{ "llu", "u", "unsigned long long", pfcheck_type, pfprint_uint },{ "llx", "x", "long long", pfcheck_xlonglong, pfprint_uint },{ "llX", "X", "long long", pfcheck_xlonglong, pfprint_uint },{ "Le",	"e", "long double", pfcheck_type, pfprint_fp },{ "LE",	"E", "long double", pfcheck_type, pfprint_fp },{ "Lf",	"f", "long double", pfcheck_type, pfprint_fp },{ "Lg",	"g", "long double", pfcheck_type, pfprint_fp },{ "LG",	"G", "long double", pfcheck_type, pfprint_fp },{ "o", "o", pfproto_xint, pfcheck_xint, pfprint_uint },{ "p", "x", pfproto_addr, pfcheck_addr, pfprint_uint },{ "s", "s", "char [] or string (or use stringof)", pfcheck_str, pfprint_cstr },{ "S", "s", pfproto_cstr, pfcheck_str, pfprint_estr },{ "T", "s", "uint64_t", pfcheck_type, pfprint_time822 },{ "u", "u", pfproto_xint, pfcheck_xint, pfprint_uint },{ "wc",	"wc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */{ "ws", "ws", pfproto_wstr, pfcheck_wstr, pfprint_wstr },{ "x", "x", pfproto_xint, pfcheck_xint, pfprint_uint },{ "X", "X", pfproto_xint, pfcheck_xint, pfprint_uint },{ "Y", "s", "uint64_t", pfcheck_type, pfprint_time },{ "%", "%", "void", pfcheck_type, pfprint_pct },{ NULL, NULL, NULL, NULL, NULL }};intdt_pfdict_create(dtrace_hdl_t *dtp){	uint_t n = _dtrace_strbuckets;	const dt_pfconv_t *pfd;	dt_pfdict_t *pdi;	if ((pdi = malloc(sizeof (dt_pfdict_t))) == NULL ||	    (pdi->pdi_buckets = malloc(sizeof (dt_pfconv_t *) * n)) == NULL) {		free(pdi);		return (dt_set_errno(dtp, EDT_NOMEM));	}	dtp->dt_pfdict = pdi;	bzero(pdi->pdi_buckets, sizeof (dt_pfconv_t *) * n);	pdi->pdi_nbuckets = n;	for (pfd = _dtrace_conversions; pfd->pfc_name != NULL; pfd++) {		dtrace_typeinfo_t dtt;		dt_pfconv_t *pfc;		uint_t h;		if ((pfc = malloc(sizeof (dt_pfconv_t))) == NULL) {			dt_pfdict_destroy(dtp);			return (dt_set_errno(dtp, EDT_NOMEM));		}		bcopy(pfd, pfc, sizeof (dt_pfconv_t));		h = dt_strtab_hash(pfc->pfc_name, NULL) % n;		pfc->pfc_next = pdi->pdi_buckets[h];		pdi->pdi_buckets[h] = pfc;		dtt.dtt_ctfp = NULL;		dtt.dtt_type = CTF_ERR;		/*		 * The "D" container or its parent must contain a definition of		 * any type referenced by a printf conversion.  If none can be		 * found, we fail to initialize the printf dictionary.		 */		if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type(		    dtp, DTRACE_OBJ_DDEFS, pfc->pfc_tstr, &dtt) != 0) {			dt_pfdict_destroy(dtp);			return (dt_set_errno(dtp, EDT_NOCONV));		}		pfc->pfc_dctfp = dtt.dtt_ctfp;		pfc->pfc_dtype = dtt.dtt_type;		/*		 * The "C" container may contain an alternate definition of an		 * explicit conversion type.  If it does, use it; otherwise		 * just set pfc_ctype to pfc_dtype so it is always valid.		 */		if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type(		    dtp, DTRACE_OBJ_CDEFS, pfc->pfc_tstr, &dtt) == 0) {			pfc->pfc_cctfp = dtt.dtt_ctfp;			pfc->pfc_ctype = dtt.dtt_type;		} else {			pfc->pfc_cctfp = pfc->pfc_dctfp;			pfc->pfc_ctype = pfc->pfc_dtype;		}		if (pfc->pfc_check == NULL || pfc->pfc_print == NULL ||		    pfc->pfc_ofmt == NULL || pfc->pfc_tstr == NULL) {			dt_pfdict_destroy(dtp);			return (dt_set_errno(dtp, EDT_BADCONV));		}		dt_dprintf("loaded printf conversion %%%s\n", pfc->pfc_name);	}	return (0);}voiddt_pfdict_destroy(dtrace_hdl_t *dtp){	dt_pfdict_t *pdi = dtp->dt_pfdict;	dt_pfconv_t *pfc, *nfc;	uint_t i;	if (pdi == NULL)		return;	for (i = 0; i < pdi->pdi_nbuckets; i++) {		for (pfc = pdi->pdi_buckets[i]; pfc != NULL; pfc = nfc) {			nfc = pfc->pfc_next;			free(pfc);		}	}	free(pdi->pdi_buckets);	free(pdi);	dtp->dt_pfdict = NULL;}static const dt_pfconv_t *dt_pfdict_lookup(dtrace_hdl_t *dtp, const char *name){	dt_pfdict_t *pdi = dtp->dt_pfdict;	uint_t h = dt_strtab_hash(name, NULL) % pdi->pdi_nbuckets;	const dt_pfconv_t *pfc;	for (pfc = pdi->pdi_buckets[h]; pfc != NULL; pfc = pfc->pfc_next) {		if (strcmp(pfc->pfc_name, name) == 0)			break;	}	return (pfc);}static dt_pfargv_t *dt_printf_error(dtrace_hdl_t *dtp, int err){	if (yypcb != NULL)		longjmp(yypcb->pcb_jmpbuf, err);	(void) dt_set_errno(dtp, err);	return (NULL);}dt_pfargv_t *dt_printf_create(dtrace_hdl_t *dtp, const char *s){	dt_pfargd_t *pfd, *nfd = NULL;	dt_pfargv_t *pfv;	const char *p, *q;	char *format;	if ((pfv = malloc(sizeof (dt_pfargv_t))) == NULL ||	    (format = strdup(s)) == NULL) {		free(pfv);		return (dt_printf_error(dtp, EDT_NOMEM));	}	pfv->pfv_format = format;	pfv->pfv_argv = NULL;	pfv->pfv_argc = 0;	pfv->pfv_flags = 0;	for (q = format; (p = strchr(q, '%')) != NULL; q = *p ? p + 1 : p) {		uint_t namelen = 0;		int digits = 0;		int dot = 0;		char name[8];		char c;		int n;		if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) {			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_NOMEM));		}		if (pfv->pfv_argv != NULL)			nfd->pfd_next = pfd;		else			pfv->pfv_argv = pfd;		bzero(pfd, sizeof (dt_pfargd_t));		pfv->pfv_argc++;		nfd = pfd;		if (p > q) {			pfd->pfd_preflen = (size_t)(p - q);			pfd->pfd_prefix = q;		}		fmt_switch:		switch (c = *++p) {		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			if (dot == 0 && digits == 0 && c == '0') {				pfd->pfd_flags |= DT_PFCONV_ZPAD;				pfd->pfd_flags &= ~DT_PFCONV_LEFT;				goto fmt_switch;			}			for (n = 0; isdigit(c); c = *++p)				n = n * 10 + c - '0';			if (dot)				pfd->pfd_prec = n;			else				pfd->pfd_width = n;			p--;			digits++;			goto fmt_switch;		case '#':			pfd->pfd_flags |= DT_PFCONV_ALT;			goto fmt_switch;		case '*':			n = dot ? DT_PFCONV_DYNPREC : DT_PFCONV_DYNWIDTH;			if (pfd->pfd_flags & n) {				yywarn("format conversion #%u has more than "				    "one '*' specified for the output %s\n",				    pfv->pfv_argc, n ? "precision" : "width");				dt_printf_destroy(pfv);				return (dt_printf_error(dtp, EDT_COMPILER));			}			pfd->pfd_flags |= n;			goto fmt_switch;		case '+':			pfd->pfd_flags |= DT_PFCONV_SPOS;			goto fmt_switch;		case '-':			pfd->pfd_flags |= DT_PFCONV_LEFT;			pfd->pfd_flags &= ~DT_PFCONV_ZPAD;			goto fmt_switch;		case '.':			if (dot++ != 0) {				yywarn("format conversion #%u has more than "				    "one '.' specified\n", pfv->pfv_argc);				dt_printf_destroy(pfv);				return (dt_printf_error(dtp, EDT_COMPILER));			}			digits = 0;			goto fmt_switch;		case '?':			if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)				pfd->pfd_width = 16;			else				pfd->pfd_width = 8;			goto fmt_switch;		case '@':			pfd->pfd_flags |= DT_PFCONV_AGG;			goto fmt_switch;		case '\'':			pfd->pfd_flags |= DT_PFCONV_GROUP;			goto fmt_switch;		case ' ':			pfd->pfd_flags |= DT_PFCONV_SPACE;			goto fmt_switch;		case '$':			yywarn("format conversion #%u uses unsupported "			    "positional format (%%n$)\n", pfv->pfv_argc);			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_COMPILER));		case '%':			if (p[-1] == '%')				goto default_lbl; /* if %% then use "%" conv */			yywarn("format conversion #%u cannot be combined "			    "with other format flags: %%%%\n", pfv->pfv_argc);			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_COMPILER));		case '\0':			yywarn("format conversion #%u name expected before "			    "end of format string\n", pfv->pfv_argc);			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_COMPILER));		case 'h':		case 'l':		case 'L':		case 'w':			if (namelen < sizeof (name) - 2)				name[namelen++] = c;			goto fmt_switch;		default_lbl:		default:			name[namelen++] = c;			name[namelen] = '\0';		}		if (strcmp(name, "A") == 0) {			dt_ident_t *idp;			idp = dt_idhash_lookup(dtp->dt_macros, "target");			if (idp == NULL || idp->di_id == 0) {				yywarn("format conversion #%u only "				    "valid when target process is specified\n",				    pfv->pfv_argc);				dt_printf_destroy(pfv);				return (dt_printf_error(dtp, EDT_COMPILER));			}		}		pfd->pfd_conv = dt_pfdict_lookup(dtp, name);		if (pfd->pfd_conv == NULL) {			yywarn("format conversion #%u is undefined: %%%s\n",			    pfv->pfv_argc, name);			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_COMPILER));		}	}	if (*q != '\0' || *format == '\0') {		if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) {			dt_printf_destroy(pfv);			return (dt_printf_error(dtp, EDT_NOMEM));		}		if (pfv->pfv_argv != NULL)			nfd->pfd_next = pfd;		else			pfv->pfv_argv = pfd;		bzero(pfd, sizeof (dt_pfargd_t));		pfv->pfv_argc++;		pfd->pfd_prefix = q;		pfd->pfd_preflen = strlen(q);	}	return (pfv);}voiddt_printf_destroy(dt_pfargv_t *pfv){	dt_pfargd_t *pfd, *nfd;	for (pfd = pfv->pfv_argv; pfd != NULL; pfd = nfd) {		nfd = pfd->pfd_next;		free(pfd);	}	free(pfv->pfv_format);	free(pfv);}voiddt_printf_validate(dt_pfargv_t *pfv, uint_t flags,    dt_ident_t *idp, int foff, dtrace_actkind_t kind, dt_node_t *dnp){	dt_pfargd_t *pfd = pfv->pfv_argv;	const char *func = idp->di_name;	char n[DT_TYPE_NAMELEN];	dtrace_typeinfo_t dtt;	const char *aggtype;	dt_node_t aggnode;	int i, j;	if (pfv->pfv_format[0] == '\0') {		xyerror(D_PRINTF_FMT_EMPTY,		    "%s( ) format string is empty\n", func);	}	/*	 * We fake up a parse node representing the type that can be used with	 * an aggregation result conversion.  For now we hardcode the signed	 * aggregations; this will be fixed later when sign issues are fixed.	 */	if (kind == DTRACEAGG_QUANTIZE || kind == DTRACEAGG_LQUANTIZE)		aggtype = "int64_t";	else		aggtype = "uint64_t";	if (dt_type_lookup(aggtype, &dtt) != 0)		xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);	bzero(&aggnode, sizeof (aggnode));	dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);	for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {		const dt_pfconv_t *pfc = pfd->pfd_conv;		const char *dyns[2];		int dync = 0;		char vname[64];		dt_node_t *vnp;		if (pfc == NULL)			continue; /* no checking if argd is just a prefix */		if (pfc->pfc_print == &pfprint_pct) {			(void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt);			continue;		}		if (pfd->pfd_flags & DT_PFCONV_DYNPREC)			dyns[dync++] = ".*";		if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH)			dyns[dync++] = "*";		for (; dync != 0; dync--) {			if (dnp == NULL) {				xyerror(D_PRINTF_DYN_PROTO,				    "%s( ) prototype mismatch: conversion "				    "#%d (%%%s) is missing a corresponding "				    "\"%s\" argument\n", func, i + 1,				    pfc->pfc_name, dyns[dync - 1]);			}			if (dt_node_is_integer(dnp) == 0) {				xyerror(D_PRINTF_DYN_TYPE,				    "%s( ) argument #%d is incompatible "				    "with conversion #%d prototype:\n"				    "\tconversion: %% %s %s\n"				    "\t prototype: int\n\t  argument: %s\n",				    func, j + foff + 1, i + 1,				    dyns[dync - 1], pfc->pfc_name,				    dt_node_type_name(dnp, n, sizeof (n)));			}			dnp = dnp->dn_list;			j++;		}		/*		 * If this conversion is consuming the aggregation data, set		 * the value node pointer (vnp) to a fake node based on the		 * aggregating function result type.  Otherwise assign vnp to		 * the next parse node in the argument list, if there is one.		 */		if (pfd->pfd_flags & DT_PFCONV_AGG) {			if (!(flags & DT_PRINTF_AGGREGATION)) {				xyerror(D_PRINTF_AGG_CONV,				    "%%@ conversion requires an aggregation"				    " and is not for use with %s( )\n", func);			}			(void) strlcpy(vname, "aggregating action",			    sizeof (vname));

⌨️ 快捷键说明

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