FreeBSD/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
/*
 * Print out an array.  This is somewhat complex, as we must manually visit
 * each member, and recursively invoke ctf_type_visit() for each member.  If
 * the members are non-structs, then we print them out directly:
 *
 * 	[ 0x14, 0x2e, 0 ]
 *
 * If they are structs, then we print out the necessary leading and trailing
 * braces, to end up with:
 *
 *	[
 *	    type {
 *	    ...
 *	    },
 *	    type {
 *	    ...
 *	    }
 *	]
 *
 * We also use a heuristic to detect whether the array looks like a character
 * array.  If the encoding indicates it's a character, and we have all
 * printable characters followed by a null byte, then we display it as a
 * string:
 *
 *	[ "string" ]
 */
Print out an array.  This is somewhat complex, as we must manually visit
each member, and recursively invoke ctf_type_visit() for each member.  If
the members are non-structs, then we print them out directly.



If they are structs, then we print out the necessary leading and trailing
braces, to end up with.



We also use a heuristic to detect whether the array looks like a character
array.  If the encoding indicates it's a character, and we have all
printable characters followed by a null byte, then we display it as a
string.


Print out an array . This is somewhat complex as we must manually visit each member and recursively invoke ctf_type_visit () for each member . If the members are non - structs then we print them out directly . If they are structs then we print out the necessary leading and trailing braces to end up with . We also use a heuristic to detect whether the array looks like a character array . If the encoding indicates it ' s a character and we have all printable characters followed by a null byte then we display it as a string .
static void
dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
{
	FILE *fp = pap->pa_file;
	ctf_file_t *ctfp = pap->pa_ctfp;
	caddr_t addr = pap->pa_addr + off / NBBY;
	ctf_arinfo_t car;
	ssize_t eltsize;
	ctf_encoding_t e;
	int i;
	boolean_t isstring;
	int kind;
	ctf_id_t rtype;
	if (ctf_array_info(ctfp, base, &car) == CTF_ERR) {
		(void) fprintf(fp, "0x%p", (void *)addr);
		return;
	}
	if ((eltsize = ctf_type_size(ctfp, car.ctr_contents)) < 0 ||
	    (rtype = ctf_type_resolve(ctfp, car.ctr_contents)) == CTF_ERR ||
	    (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR) {
		(void) fprintf(fp, "<invalid type %lu>", car.ctr_contents);
		return;
	}
	isstring = B_FALSE;
	if (kind == CTF_K_INTEGER &&
	    ctf_type_encoding(ctfp, rtype, &e) != CTF_ERR && CTF_IS_CHAR(e)) {
		char c;
		for (i = 0; i < car.ctr_nelems; i++) {
			c = *((char *)addr + eltsize * i);
			if (!isprint(c) || c == '\0')
				break;
		}
		if (i != car.ctr_nelems && c == '\0')
			isstring = B_TRUE;
	}
	if (!isstring || pap->pa_depth != 0)
		(void) fprintf(fp, "[ ");
	if (isstring)
		(void) fprintf(fp, "\"");
	for (i = 0; i < car.ctr_nelems; i++) {
		if (isstring) {
			char c = *((char *)addr + eltsize * i);
			if (c == '\0')
				break;
			(void) fprintf(fp, "%c", c);
		} else {
			dt_printarg_t pa = *pap;
			pa.pa_nest += pap->pa_depth + 1;
			pa.pa_depth = 0;
			pa.pa_addr = addr + eltsize * i;
			(void) ctf_type_visit(ctfp, car.ctr_contents,
			    dt_print_member, &pa);
			dt_print_trailing_braces(&pa, 0);
			if (i != car.ctr_nelems - 1)
				(void) fprintf(fp, ", ");
			else if (CTF_IS_STRUCTLIKE(kind))
				(void) fprintf(fp, "\n");
		}
	}
	if (isstring)
		(void) fprintf(fp, "\"");
	if (!isstring || pap->pa_depth != 0) {
		if (CTF_IS_STRUCTLIKE(kind))
			dt_print_indent(pap);
		else
			(void) fprintf(fp, " ");
		(void) fprintf(fp, "]");
	}
}
static void dt_print_array ( ctf_id_t base , ulong_t off , dt_printarg_t * pap ) { FILE * fp = pap -> pa_file ; ctf_file_t * ctfp = pap -> pa_ctfp ; caddr_t addr = pap -> pa_addr + off / NBBY ; ctf_arinfo_t car ; ssize_t eltsize ; ctf_encoding_t e ; int i ; boolean_t isstring ; int kind ; ctf_id_t rtype ; if ( ctf_array_info ( ctfp , base , & car ) == CTF_ERR ) { ( void ) fprintf ( fp , " " , ( void * ) addr ) ; return ; } if ( ( eltsize = ctf_type_size ( ctfp , car . ctr_contents ) ) < 0 || ( rtype = ctf_type_resolve ( ctfp , car . ctr_contents ) ) == CTF_ERR || ( kind = ctf_type_kind ( ctfp , rtype ) ) == CTF_ERR ) { ( void ) fprintf ( fp , " " , car . ctr_contents ) ; return ; } isstring = B_FALSE ; if ( kind == CTF_K_INTEGER && ctf_type_encoding ( ctfp , rtype , & e ) != CTF_ERR && CTF_IS_CHAR ( e ) ) { char c ; for ( i = 0 ; i < car . ctr_nelems ; i ++ ) { c = * ( ( char * ) addr + eltsize * i ) ; if ( ! isprint ( c ) || c == ' \0 ' ) break ; } if ( i != car . ctr_nelems && c == ' \0 ' ) isstring = B_TRUE ; } if ( ! isstring || pap -> pa_depth != 0 ) ( void ) fprintf ( fp , " " ) ; if ( isstring ) ( void ) fprintf ( fp , " \" " ) ; for ( i = 0 ; i < car . ctr_nelems ; i ++ ) { if ( isstring ) { char c = * ( ( char * ) addr + eltsize * i ) ; if ( c == ' \0 ' ) break ; ( void ) fprintf ( fp , " " , c ) ; } else { dt_printarg_t pa = * pap ; pa . pa_nest += pap -> pa_depth + 1 ; pa . pa_depth = 0 ; pa . pa_addr = addr + eltsize * i ; ( void ) ctf_type_visit ( ctfp , car . ctr_contents , dt_print_member , & pa ) ; dt_print_trailing_braces ( & pa , 0 ) ; if ( i != car . ctr_nelems - 1 ) ( void ) fprintf ( fp , " " ) ; else if ( CTF_IS_STRUCTLIKE ( kind ) ) ( void ) fprintf ( fp , " \n " ) ; } } if ( isstring ) ( void ) fprintf ( fp , " \" " ) ; if ( ! isstring || pap -> pa_depth != 0 ) { if ( CTF_IS_STRUCTLIKE ( kind ) ) dt_print_indent ( pap ) ; else ( void ) fprintf ( fp , " " ) ; ( void ) fprintf ( fp , " " ) ; } }
Print out an array.
Print out an array .
/* see if this looks like a string */ /*
	 * As a slight aesthetic optimization, if we are a top-level type, then
	 * don't bother printing out the brackets.  This lets print("foo") look
	 * like:
	 *
	 * 	string "foo"
	 *
	 * As D will internally represent this as a char[256] array.
	 */ /*
			 * Recursively invoke ctf_type_visit() on each member.
			 * We setup a new printarg struct with 'pa_nest' set to
			 * indicate that we are within a nested array.
			 */