/*
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */
#include <lcrash.h>

/*
 * stab_type_banner()
 */
void
stab_type_banner(FILE *ofp, int flags)
{
	print_banner(ofp, "NAME                      TYPE     "
		"        TYPE_NUM         REAL_TYPE  SIZE%}79", flags);
}

/*
 * ktype_banner()
 */
void
ktype_banner(FILE *ofp, int flags)
{
	stab_type_banner(ofp, flags);
}

/*
 * print_stab_type()
 */
void
print_stab_type(stab_type_t *sp, int flags, FILE *ofp)
{
	fprintf(ofp, "%-25s ", sp->st_name);
	switch(sp->st_type) {
		case KLT_BASE:
			fprintf(ofp, "BASE     ");
			break;
		case KLT_STRUCT:
			fprintf(ofp, "STRUCT   ");
			break;
		case KLT_UNION:
			fprintf(ofp, "UNION    ");
			break;
		case KLT_ENUMERATION:
			fprintf(ofp, "ENUM     ");
			break;
		case KLT_MEMBER :
			fprintf(ofp, "MEMBER   ");
			break;
		case KLT_ARRAY:
			fprintf(ofp, "ARRAY    ");
			break;
		case KLT_POINTER:
			fprintf(ofp, "POINTER  ");
			break;
		case KLT_TYPEDEF:
			fprintf(ofp, "TYPEDEF  ");
			break;
		case KLT_FUNCTION:
			fprintf(ofp, "FUNCTION ");
			break;
		case KLT_INCOMPLETE:
			fprintf(ofp, "INCOMPLETE");
			break;
		default:
			fprintf(ofp, "UNKNOWN  ");
	}
	fprintf(ofp, "%016"FMT64"x  ", sp->st_type_num);
	fprintf(ofp, "%016"FMT64"x ", sp->st_real_type);
	fprintf(ofp, "%4d\n", sp->st_size);
	if (flags & C_FULL) {
		fprintf(ofp, "  ST_BIT_OFFSET=%d, ST_BIT_SIZE=%d\n",
			sp->st_bit_offset, sp->st_bit_size);
		fprintf(ofp, "  ELEMENT_TYPE=0x%"FMT64"x, "
			"INDEX_TYPE=0x%"FMT64"x, VALUE=%d\n", 
			sp->st_element_type, 
			sp->st_index_type, sp->st_value);
		fprintf(ofp, "  FLAGS=0x%x, OFFSET=%d\n",
			sp->st_flags, sp->st_offset);
		fprintf(ofp, "  TYPESTR=\"%s\"\n", sp->st_typestr);
		fprintf(ofp, "  LOW_BOUNDS=%d, HIGH_BOUNDS=%d, "
				"MEMBER=0x%lx, NEXT=0x%lx\n",
			sp->st_low_bounds, sp->st_high_bounds,
			(long unsigned int)sp->st_member, 
			(long unsigned int)sp->st_next);
		fprintf(ofp, "\n");
	}
}

/*
 * print_ktype()
 */
void
print_ktype(kltype_t *kltp, int flags, FILE *ofp)
{
	print_stab_type((stab_type_t *)kltp, flags, ofp);
}

/*
 * walk_stab_type()
 */
void
walk_stab_type(stab_type_t *sp, int flags, FILE *ofp)
{
	int type_num;
	stab_type_t *mp;

	stab_type_banner(ofp, (BANNER|SMAJOR));
	print_stab_type(sp, flags, ofp);
	if ((mp = (stab_type_t *)sp->st_member)) {
		while (mp) {
			print_stab_type(mp, flags, ofp);
			mp = (stab_type_t *)mp->st_member;
		}
		fprintf(ofp, "\n");
	} else if (sp->st_real_type && 
			(sp->st_type_num != sp->st_real_type)) {
		type_num = sp->st_real_type;
		while (type_num) {
			if ((mp = st_find_type((char *)NULL, type_num))) {
				fprintf(ofp, "\n");
				stab_type_banner(ofp, (BANNER|SMINOR));
				print_stab_type(mp, flags, ofp);
				if (mp->st_type_num != mp->st_real_type) {
					type_num = mp->st_real_type;
				} else {
					type_num = 0;
				}
			} else {
				type_num = 0;
			}
		}
		fprintf(ofp, "\n");
	} 
}

/*
 * walk_ktyp()
 */
void
walk_ktype(kltype_t *kltp, int flags, FILE *ofp)
{
	walk_stab_type((stab_type_t *)kltp, flags, ofp);
}

/*
 * list_stab_types()
 */
int
list_stab_types(int flags, FILE *ofp)
{
	int cnt = 0;
	stab_type_t *sp, *tsp, *nextsp;

	tsp = (stab_type_t *)kl_first_sym(KLT_TYPEDEF);
	sp = (stab_type_t *)kl_first_sym(KLT_TYPE);
	if (tsp) {
		if (sp) {
			if (strcmp(sp->st_name, tsp->st_name) < 0) {
				nextsp = sp;
			} else {
				nextsp = tsp;
			}
		} else {
			nextsp = tsp;
		}
	} else if (sp) {
		nextsp = sp;
	} else {
		return(0);
	}

	while (nextsp) {
		if (flags & C_LIST) {
			if (flags & C_FULL) {
				stab_type_banner(ofp, (BANNER|SMAJOR));
			}
			if (flags & C_NEXT) {
				walk_stab_type(nextsp, flags, ofp);
			} else {
				print_stab_type(nextsp, flags, ofp);
			}
		} else {
			kl_print_type((void *)NULL, 
				(kltype_t*)nextsp, 0, flags, ofp);
		}
		cnt++;

		if (nextsp == sp) {
			sp = (stab_type_t *)kl_next_sym((kltype_t*)sp);
		} else {
			tsp = (stab_type_t *)kl_next_sym((kltype_t*)tsp);
		}
		if (tsp) {
			if (sp) {
				if (strcmp(sp->st_name, tsp->st_name) < 0) {
					nextsp = sp;
				} else {
					nextsp = tsp;
				}
			} else {
				nextsp = tsp;
			}
		} else if (sp) {
			nextsp = sp;
		} else {
			nextsp = (stab_type_t *)NULL;
		}
	}
	return(cnt);
}

/*
 * list_ktypes()
 */
int
list_ktypes(int flags, FILE *ofp)
{
	return(list_stab_types(flags, ofp));
}
