diff leo-obj/tool/richsym.c @ 145:25d3ead621f8

tiobjd: ctypes command implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 29 Apr 2014 04:49:17 +0000
parents fd772de226cb
children 70631c246df0
line wrap: on
line diff
--- a/leo-obj/tool/richsym.c	Mon Apr 28 08:04:39 2014 +0000
+++ b/leo-obj/tool/richsym.c	Tue Apr 29 04:49:17 2014 +0000
@@ -15,6 +15,8 @@
 extern unsigned get_u16(), get_u32();
 extern char *storage_class_to_string();
 
+int richsym_print_bitsize;
+
 static int
 try_typedef_hack(struct_sym)
 	struct internal_syment *struct_sym;
@@ -182,3 +184,184 @@
 		return("__unknown_base_type");
 	}
 }
+
+richsym_print_in_c(prefix, sym, is_typedef)
+	char *prefix;
+	struct internal_syment *sym;
+{
+	char *base_type, *s1, *s2;
+	int dertype, last_ptr, narray;
+
+	base_type = get_base_type_of_syment(sym, is_typedef);
+	dertype = sym->type >> 4;
+	s1 = malloc(strlen(sym->name));
+	if (!s1) {
+		perror("malloc");
+		exit(1);
+	}
+	strcpy(s1, sym->name + 1);
+	last_ptr = 0;
+	narray = 0;
+	for (; dertype; dertype >>= 2) {
+		switch (dertype & 3) {
+		case DT_NON:
+			fprintf(stderr,
+		"error: symbol #%u: DT_NON followed by more derived types\n",
+				sym->number);
+			exit(1);
+		case DT_PTR:
+			s2 = malloc(strlen(s1) + 2);
+			if (!s2) {
+				perror("malloc");
+				exit(1);
+			}
+			sprintf(s2, "*%s", s1);
+			free(s1);
+			s1 = s2;
+			last_ptr = 1;
+			continue;
+		}
+		if (last_ptr) {
+			s2 = malloc(strlen(s1) + 3);
+			if (!s2) {
+				perror("malloc");
+				exit(1);
+			}
+			sprintf(s2, "(%s)", s1);
+			free(s1);
+			s1 = s2;
+		}
+		switch (dertype & 3) {
+		case DT_FCN:
+			s2 = malloc(strlen(s1) + 3);
+			if (!s2) {
+				perror("malloc");
+				exit(1);
+			}
+			sprintf(s2, "%s()", s1);
+			free(s1);
+			s1 = s2;
+			break;
+		case DT_ARY:
+			if (narray >= 4) {
+				fprintf(stderr,
+				"error: symbol #%u: too many [] types\n",
+					sym->number);
+				exit(1);
+			}
+			s2 = malloc(strlen(s1) + 8);
+			if (!s2) {
+				perror("malloc");
+				exit(1);
+			}
+			sprintf(s2, "%s[%u]", s1,
+				get_u16(sym->aux + 8 + narray * 2));
+			free(s1);
+			s1 = s2;
+			narray++;
+			break;
+		default:
+			fprintf(stderr,
+			"BUG in richsym_print_in_c(): bad derived type\n");
+			exit(1);
+		}
+		last_ptr = 0;
+	}
+	printf("%s%s %s;", prefix, base_type, s1);
+	free(s1);
+	if (richsym_print_bitsize)
+		printf("\t/* %u bits */", get_u32(sym->aux + 4));
+	putchar('\n');
+}
+
+cmd_ctypes(argc, argv)
+	char **argv;
+{
+	int c;
+	unsigned n;
+	struct internal_syment *sym;
+
+	while ((c = getopt(argc, argv, "b")) != EOF)
+		switch (c) {
+		case 'b':
+			richsym_print_bitsize++;
+			continue;
+		default:
+			/* error msg already printed */
+			exit(1);
+		}
+
+	get_int_section_table();
+	get_int_symbol_table();
+	richsym_initial_preen();
+	for (n = 0; n < nsymtab; n++) {
+		sym = symtab[n];
+		if (!sym)
+			continue;
+		switch (sym->class) {
+		case C_FILE:
+			printf("/* from %s */\n", sym->name);
+			continue;
+		case C_STRTAG:
+		case C_UNTAG:
+		case C_ENTAG:
+			printf("%s {", sym->struct_name_raw);
+			if (richsym_print_bitsize && sym->aux)
+				printf("\t/* %u bits */", get_u32(sym->aux+4));
+			putchar('\n');
+			continue;
+		case C_EOS:
+			fputs("};", stdout);
+			if (richsym_print_bitsize && sym->aux)
+				printf("\t/* %u bits */", get_u32(sym->aux+4));
+			putchar('\n');
+			continue;
+		case C_MOS:
+		case C_MOU:
+		case C_MOE:
+		case C_TPDEF:
+			break;
+		default:
+			continue;
+		}
+		if (sym->name[0] != '_') {
+			printf(
+		"/* symbol #%u of class %s has no leading underscore */\n",
+				sym->number,
+				storage_class_to_string(sym->class, 0));
+			continue;
+		}
+		if (!sym->aux && sym->class != C_MOE) {
+			printf(
+			"/* symbol #%u of class %s has no aux record */\n",
+				sym->number,
+				storage_class_to_string(sym->class, 0));
+			continue;
+		}
+		switch (sym->class) {
+		case C_MOS:
+		case C_MOU:
+			if (sym->scnum != -1)
+				printf("\t/* MOS/MOU section != ABS! */\n");
+			else if (richsym_print_bitsize >= 2)
+				printf("\t/* offset: %u bits\n", sym->value);
+			richsym_print_in_c("\t", sym, 0);
+			continue;
+		case C_MOE:
+			if (sym->scnum != -1) {
+				printf("\t/* MOE section != ABS! */\n");
+				continue;
+			}
+			printf("\t%s = %u;", sym->name + 1, sym->value);
+			if (sym->value >= 10)
+				printf("\t/* 0x%x */", sym->value);
+			putchar('\n');
+			continue;
+		case C_TPDEF:
+			richsym_print_in_c("typedef ", sym,
+						!(sym->type & 0xFFF0));
+			continue;
+		}
+	}
+	exit(0);
+}