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

📄 dt_printf.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
			vnp = &aggnode;		} else if (dnp == NULL) {			xyerror(D_PRINTF_ARG_PROTO,			    "%s( ) prototype mismatch: conversion #%d (%%"			    "%s) is missing a corresponding value argument\n",			    func, i + 1, pfc->pfc_name);		} else {			(void) snprintf(vname, sizeof (vname),			    "argument #%d", j + foff + 1);			vnp = dnp;			dnp = dnp->dn_list;			j++;		}		/*		 * Fill in the proposed final format string by prepending any		 * size-related prefixes to the pfconv's format string.  The		 * pfc_check() function below may optionally modify the format		 * as part of validating the type of the input argument.		 */		if (pfc->pfc_print == &pfprint_sint ||		    pfc->pfc_print == &pfprint_uint ||		    pfc->pfc_print == &pfprint_dint) {			if (dt_node_type_size(vnp) == sizeof (uint64_t))				(void) strcpy(pfd->pfd_fmt, "ll");		} else if (pfc->pfc_print == &pfprint_fp) {			if (dt_node_type_size(vnp) == sizeof (long double))				(void) strcpy(pfd->pfd_fmt, "L");		}		(void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt);		/*		 * Validate the format conversion against the value node type.		 * If the conversion is good, create the descriptor format		 * string by concatenating together any required printf(3C)		 * size prefixes with the conversion's native format string.		 */		if (pfc->pfc_check(pfd, vnp) == 0) {			xyerror(D_PRINTF_ARG_TYPE,			    "%s( ) %s is incompatible with "			    "conversion #%d prototype:\n\tconversion: %%%s\n"			    "\t prototype: %s\n\t  argument: %s\n", func,			    vname, i + 1, pfc->pfc_name, pfc->pfc_tstr,			    dt_node_type_name(vnp, n, sizeof (n)));		}	}	if ((flags & DT_PRINTF_EXACTLEN) && dnp != NULL) {		xyerror(D_PRINTF_ARG_EXTRA,		    "%s( ) prototype mismatch: only %d arguments "		    "required by this format string\n", func, j);	}	pfv->pfv_flags = flags;}static intdt_printf_getint(dtrace_hdl_t *dtp, const dtrace_recdesc_t *recp,    uint_t nrecs, const void *buf, size_t len, int *ip){	uintptr_t addr;	if (nrecs == 0)		return (dt_set_errno(dtp, EDT_DMISMATCH));	addr = (uintptr_t)buf + recp->dtrd_offset;	if (addr + sizeof (int) > (uintptr_t)buf + len)		return (dt_set_errno(dtp, EDT_DOFFSET));	if (addr & (recp->dtrd_alignment - 1))		return (dt_set_errno(dtp, EDT_DALIGN));	switch (recp->dtrd_size) {	case sizeof (int8_t):		*ip = (int)*((int8_t *)addr);		break;	case sizeof (int16_t):		*ip = (int)*((int16_t *)addr);		break;	case sizeof (int32_t):		*ip = (int)*((int32_t *)addr);		break;	case sizeof (int64_t):		*ip = (int)*((int64_t *)addr);		break;	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}	return (0);}/*ARGSUSED*/static intpfprint_average(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	const uint64_t *data = addr;	if (size != sizeof (uint64_t) * 2)		return (dt_set_errno(dtp, EDT_DMISMATCH));	return (dt_printf(dtp, fp, format,	    data[0] ? data[1] / normal / data[0] : 0));}/*ARGSUSED*/static intpfprint_quantize(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_print_quantize(dtp, fp, addr, size, normal));}/*ARGSUSED*/static intpfprint_lquantize(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_print_lquantize(dtp, fp, addr, size, normal));}static intdt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,    const dtrace_recdesc_t *recs, uint_t nrecs, const void *buf,    size_t len, uint64_t normal){	dt_pfargd_t *pfd = pfv->pfv_argv;	const dtrace_recdesc_t *recp = recs;	const dtrace_recdesc_t *aggr = NULL;	uchar_t *lim = (uchar_t *)buf + len;	char format[64] = "%";	int i;	/*	 * If we are formatting an aggregation, set 'aggr' to the final record	 * description (the aggregation result) so we can use this record with	 * any conversion where DT_PFCONV_AGG is set.  We then decrement nrecs	 * to prevent this record from being used with any other conversion.	 */	if (pfv->pfv_flags & DT_PRINTF_AGGREGATION) {		if (nrecs == 0)			return (dt_set_errno(dtp, EDT_DMISMATCH));		aggr = recp + nrecs - 1;		nrecs--;	}	for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {		const dt_pfconv_t *pfc = pfd->pfd_conv;		int width = pfd->pfd_width;		int prec = pfd->pfd_prec;		int rval;		char *f = format + 1; /* skip initial '%' */		const dtrace_recdesc_t *rec;		dt_pfprint_f *func;		uchar_t *addr;		size_t size;		if (pfd->pfd_preflen != 0) {			char *tmp = alloca(pfd->pfd_preflen + 1);			bcopy(pfd->pfd_prefix, tmp, pfd->pfd_preflen);			tmp[pfd->pfd_preflen] = '\0';			if ((rval = dt_printf(dtp, fp, tmp)) < 0)				return (rval);		}		if (pfc == NULL) {			if (pfv->pfv_argc == 1)				return (nrecs != 0);			continue;		}		/*		 * If the conversion is %%, just invoke the print callback		 * with no data record and continue; it consumes no record.		 */		if (pfc->pfc_print == &pfprint_pct) {			if (pfc->pfc_print(dtp, fp, NULL, pfd, NULL, 0, 1) >= 0)				continue;			return (-1); /* errno is set for us */		}		if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH) {			if (dt_printf_getint(dtp, recp++, nrecs--, buf,			    len, &width) == -1)				return (-1); /* errno is set for us */			pfd->pfd_dynwidth = width;		} else {			pfd->pfd_dynwidth = 0;		}		if ((pfd->pfd_flags & DT_PFCONV_DYNPREC) && dt_printf_getint(		    dtp, recp++, nrecs--, buf, len, &prec) == -1)			return (-1); /* errno is set for us */		if (pfd->pfd_flags & DT_PFCONV_AGG) {			if (aggr == NULL)				return (dt_set_errno(dtp, EDT_DMISMATCH));			rec = aggr;		} else {			if (nrecs == 0)				return (dt_set_errno(dtp, EDT_DMISMATCH));			rec = recp++;			nrecs--;		}		addr = (uchar_t *)buf + rec->dtrd_offset;		size = rec->dtrd_size;		if (addr + size > lim) {			dt_dprintf("bad size: addr=%p size=0x%x lim=%p\n",			    (void *)addr, rec->dtrd_size, (void *)lim);			return (dt_set_errno(dtp, EDT_DOFFSET));		}		if (rec->dtrd_alignment != 0 &&		    ((uintptr_t)addr & (rec->dtrd_alignment - 1)) != 0) {			dt_dprintf("bad align: addr=%p size=0x%x align=0x%x\n",			    (void *)addr, rec->dtrd_size, rec->dtrd_alignment);			return (dt_set_errno(dtp, EDT_DALIGN));		}		switch (rec->dtrd_action) {		case DTRACEAGG_AVG:			func = pfprint_average;			break;		case DTRACEAGG_QUANTIZE:			func = pfprint_quantize;			break;		case DTRACEAGG_LQUANTIZE:			func = pfprint_lquantize;			break;		default:			func = pfc->pfc_print;			break;		}		if (pfd->pfd_flags & DT_PFCONV_ALT)			*f++ = '#';		if (pfd->pfd_flags & DT_PFCONV_ZPAD)			*f++ = '0';		if (pfd->pfd_flags & DT_PFCONV_LEFT)			*f++ = '-';		if (pfd->pfd_flags & DT_PFCONV_SPOS)			*f++ = '+';		if (pfd->pfd_flags & DT_PFCONV_GROUP)			*f++ = '\'';		if (pfd->pfd_flags & DT_PFCONV_SPACE)			*f++ = ' ';		/*		 * If we're printing a stack and DT_PFCONV_LEFT is set, we		 * don't add the width to the format string.  See the block		 * comment in pfprint_stack() for a description of the		 * behavior in this case.		 */		if (func == pfprint_stack && (pfd->pfd_flags & DT_PFCONV_LEFT))			width = 0;		if (width != 0)			f += snprintf(f, sizeof (format), "%d", width);		if (prec != 0)			f += snprintf(f, sizeof (format), ".%d", prec);		(void) strcpy(f, pfd->pfd_fmt);		pfd->pfd_rec = rec;		if (func(dtp, fp, format, pfd, addr, size,		    rec == aggr ? normal : 1) < 0)			return (-1); /* errno is set for us */	}	return ((int)(recp - recs));}intdtrace_sprintf(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,    const dtrace_recdesc_t *recp, uint_t nrecs, const void *buf, size_t len){	dtrace_optval_t size;	int rval;	rval = dtrace_getopt(dtp, "strsize", &size);	assert(rval == 0);	assert(dtp->dt_sprintf_buflen == 0);	if (dtp->dt_sprintf_buf != NULL)		free(dtp->dt_sprintf_buf);	if ((dtp->dt_sprintf_buf = malloc(size)) == NULL)		return (dt_set_errno(dtp, EDT_NOMEM));	bzero(dtp->dt_sprintf_buf, size);	dtp->dt_sprintf_buflen = size;	rval = dt_printf_format(dtp, fp, fmtdata, recp, nrecs, buf, len, 1);	dtp->dt_sprintf_buflen = 0;	if (rval == -1)		free(dtp->dt_sprintf_buf);	return (rval);}intdtrace_system(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,    const dtrace_recdesc_t *recp, uint_t nrecs, const void *buf, size_t len){	int rval = dtrace_sprintf(dtp, fp, fmtdata, recp, nrecs, buf, len);	if (rval == -1)		return (rval);	/*	 * Before we execute the specified command, flush fp to assure that	 * any prior dt_printf()'s appear before the output of the command	 * not after it.	 */	(void) fflush(fp);	if (system(dtp->dt_sprintf_buf) == -1)		return (dt_set_errno(dtp, errno));	return (rval);}intdtrace_fprintf(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,    const dtrace_recdesc_t *recp, uint_t nrecs, const void *buf, size_t len){	return (dt_printf_format(dtp, fp, fmtdata, recp, nrecs, buf, len, 1));}void *dtrace_printf_create(dtrace_hdl_t *dtp, const char *s){	dt_pfargv_t *pfv = dt_printf_create(dtp, s);	dt_pfargd_t *pfd;	int i;	if (pfv == NULL)		return (NULL);		/* errno has been set for us */	pfd = pfv->pfv_argv;	for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {		const dt_pfconv_t *pfc = pfd->pfd_conv;		if (pfc == NULL)			continue;		/*		 * If the output format is not %s then we assume that we have		 * been given a correctly-sized format string, so we copy the		 * true format name including the size modifier.  If the output		 * format is %s, then either the input format is %s as well or		 * it is one of our custom formats (e.g. pfprint_addr), so we		 * must set pfd_fmt to be the output format conversion "s".		 */		if (strcmp(pfc->pfc_ofmt, "s") != 0)			(void) strcat(pfd->pfd_fmt, pfc->pfc_name);		else			(void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt);	}	return (pfv);}void *dtrace_printa_create(dtrace_hdl_t *dtp, const char *s){	dt_pfargv_t *pfv = dtrace_printf_create(dtp, s);	if (pfv == NULL)		return (NULL);		/* errno has been set for us */	pfv->pfv_flags |= DT_PRINTF_AGGREGATION;	return (pfv);}/*ARGSUSED*/size_tdtrace_printf_format(dtrace_hdl_t *dtp, void *fmtdata, char *s, size_t len){	dt_pfargv_t *pfv = fmtdata;	dt_pfargd_t *pfd = pfv->pfv_argv;	/*	 * An upper bound on the string length is the length of the original	 * format string, plus three times the number of conversions (each	 * conversion could add up an additional "ll" and/or pfd_width digit	 * in the case of converting %? to %16) plus one for a terminating \0.	 */	size_t formatlen = strlen(pfv->pfv_format) + 3 * pfv->pfv_argc + 1;	char *format = alloca(formatlen);	char *f = format;	int i, j;	for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {		const dt_pfconv_t *pfc = pfd->pfd_conv;		const char *str;		int width = pfd->pfd_width;		int prec = pfd->pfd_prec;		if (pfd->pfd_preflen != 0) {			for (j = 0; j < pfd->pfd_preflen; j++)				*f++ = pfd->pfd_prefix[j];		}		if (pfc == NULL)			continue;		*f++ = '%';		if (pfd->pfd_flags & DT_PFCONV_ALT)			*f++ = '#';		if (pfd->pfd_flags & DT_PFCONV_ZPAD)			*f++ = '0';		if (pfd->pfd_flags & DT_PFCONV_LEFT)			*f++ = '-';		if (pfd->pfd_flags & DT_PFCONV_SPOS)			*f++ = '+';		if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH)			*f++ = '*';		if (pfd->pfd_flags & DT_PFCONV_DYNPREC) {			*f++ = '.';			*f++ = '*';		}		if (pfd->pfd_flags & DT_PFCONV_GROUP)			*f++ = '\'';		if (pfd->pfd_flags & DT_PFCONV_SPACE)			*f++ = ' ';		if (pfd->pfd_flags & DT_PFCONV_AGG)			*f++ = '@';		if (width != 0)			f += snprintf(f, sizeof (format), "%d", width);		if (prec != 0)			f += snprintf(f, sizeof (format), ".%d", prec);		/*		 * If the output format is %s, then either %s is the underlying		 * conversion or the conversion is one of our customized ones,		 * e.g. pfprint_addr.  In these cases, put the original string		 * name of the conversion (pfc_name) into the pickled format		 * string rather than the derived conversion (pfd_fmt).		 */		if (strcmp(pfc->pfc_ofmt, "s") == 0)			str = pfc->pfc_name;		else			str = pfd->pfd_fmt;		for (j = 0; str[j] != '\0'; j++)			*f++ = str[j];	}	*f = '\0'; /* insert nul byte; do not count in return value */	assert(f < format + formatlen);	(void) strncpy(s, format, len);	return ((size_t)(f - format));}static intdt_fprinta(dtrace_aggdata_t *adp, void *arg){	dtrace_aggdesc_t *agg = adp->dtada_desc;	const dtrace_recdesc_t *recp = &agg->dtagd_rec[0];	uint_t nrecs = agg->dtagd_nrecs;	dt_pfwalk_t *pfw = arg;	int id;	if (dt_printf_getint(pfw->pfw_dtp, recp++, nrecs--,	    adp->dtada_data, adp->dtada_size, &id) != 0 || pfw->pfw_aid != id)		return (0); /* no aggregation id or id does not match */	if (dt_printf_format(pfw->pfw_dtp, pfw->pfw_fp, pfw->pfw_argv,	    recp, nrecs, adp->dtada_data, adp->dtada_size,	    adp->dtada_normal) == -1)		return (pfw->pfw_err = pfw->pfw_dtp->dt_errno);	agg->dtagd_flags |= DTRACE_AGD_PRINTED;	if (dt_buffered_flush(pfw->pfw_dtp, NULL, &agg->dtagd_rec[0], adp) < 0)		return (-1);	return (0);}intdtrace_fprinta(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,    const dtrace_recdesc_t *recs, uint_t nrecs, const void *buf, size_t len){	const dtrace_recdesc_t *recp = recs;	dt_pfwalk_t pfw;	int id;	if (dt_printf_getint(dtp, recp++, nrecs--, buf, len, &id) == -1)		return (-1); /* errno is set for us */	pfw.pfw_dtp = dtp;	pfw.pfw_argv = fmtdata;	pfw.pfw_aid = id;	pfw.pfw_fp = fp;	pfw.pfw_err = 0;	if (dtrace_aggregate_walk_valsorted(dtp, dt_fprinta, &pfw) == -1 ||	    pfw.pfw_err != 0)		return (-1); /* errno is set for us */	return ((int)(recp - recs));}

⌨️ 快捷键说明

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