scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

size.c (2763B)


      1 #include <errno.h>
      2 #include <limits.h>
      3 #include <stdarg.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 #include <scc/arg.h>
      9 #include <scc/mach.h>
     10 
     11 struct sizes {
     12 	unsigned long long text;
     13 	unsigned long long data;
     14 	unsigned long long bss;
     15 };
     16 
     17 static int status;
     18 static char *filename, *membname;
     19 static int tflag;
     20 static unsigned long long ttext, tdata, tbss, ttotal;
     21 char *argv0;
     22 
     23 static void
     24 error(char *fmt, ...)
     25 {
     26 	va_list va;
     27 
     28 	va_start(va, fmt);
     29 	fprintf(stderr, "size: %s: ", filename);
     30 	if (membname)
     31 		fprintf(stderr, "%s: ", membname);
     32 	vfprintf(stderr, fmt, va);
     33 	putc('\n', stderr);
     34 	va_end(va);
     35 
     36 	status = EXIT_FAILURE;
     37 }
     38 
     39 static void
     40 newobject(FILE *fp, int type)
     41 {
     42 	int i;
     43 	Obj *obj;
     44 	unsigned long long total, *p;
     45 	Objsect *sp;
     46 	struct sizes siz;
     47 
     48 	if ((obj = objnew(type)) == NULL) {
     49 		error("out of memory");
     50 		return;
     51 	}
     52 
     53 	if (objread(obj, fp) < 0 || objsect(obj) < 0) {
     54 		error("file corrupted");
     55 		goto err;
     56 	}
     57 
     58 	siz.text = siz.data = siz.bss = 0;
     59 	for (sp = obj->secs; sp; sp = sp->next) {
     60 		switch (sp->type) {
     61 		case 'T':
     62 			p = &siz.text;
     63 			break;
     64 		case 'D':
     65 			p = &siz.data;
     66 			break;
     67 		case 'B':
     68 			p = &siz.bss;
     69 			break;
     70 		default:
     71 			continue;
     72 		}
     73 
     74 		if (*p > ULLONG_MAX - sp->size) {
     75 			error("integer overflow");
     76 			goto err;
     77 		}
     78 			
     79 		*p += sp->size;
     80 	}
     81 
     82 	total = siz.text + siz.data + siz.bss;
     83 	printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
     84 	       siz.text,
     85 	       siz.data,
     86 	       siz.bss,
     87 	       total, total, filename);
     88 
     89 	ttext += siz.text;
     90 	tdata += siz.data;
     91 	tbss += siz.bss;
     92 	ttotal += total;
     93 
     94 err:
     95 	objdel(obj);
     96 }
     97 
     98 static int
     99 newmember(FILE *fp, char *name, void *data)
    100 {
    101 	int t;
    102 
    103 	membname = name;
    104 	if ((t = objtype(fp, NULL)) != -1)
    105 		newobject(fp, t);
    106 
    107 	return 1;
    108 }
    109 
    110 static void
    111 size(char *fname)
    112 {
    113 	int t;
    114 	FILE *fp;
    115 
    116 	filename = fname;
    117 	if ((fp = fopen(fname, "rb")) == NULL) {
    118 		error(strerror(errno));
    119 		return;
    120 	}
    121 
    122 	if ((t = objtype(fp, NULL)) != -1) {
    123 		newobject(fp, t);
    124 	} else if (archive(fp)) {
    125 		if (formember(fp, newmember, NULL) < 0)
    126 			error("library corrupted");
    127 	} else {
    128 		error("bad format");
    129 	}
    130 
    131 	if (ferror(fp))
    132 		error(strerror(errno));
    133 
    134 	fclose(fp);
    135 }
    136 
    137 static void
    138 usage(void)
    139 {
    140 	fputs("usage: size [-t] [file...]\n", stderr);
    141 	exit(EXIT_FAILURE);
    142 }
    143 
    144 int
    145 main(int argc, char *argv[])
    146 {
    147 	unsigned long long total;
    148 
    149 	ARGBEGIN {
    150 	case 't':
    151 		tflag = 1;
    152 		break;
    153 	default:
    154 		usage();
    155 	} ARGEND
    156 
    157 	puts("text\tdata\tbss\tdec\thex\tfilename");
    158 
    159 	if (argc == 0) {
    160 		size("a.out");
    161 	} else {
    162 		for (; *argv; ++argv)
    163 			size(*argv);
    164 	}
    165 
    166 	if (tflag) {
    167 		total = ttext + tdata + tbss;
    168 		printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
    169 		       ttext, tdata, tbss, total, total, "(TOTALS)");
    170 	}
    171 
    172 	if (fflush(stdout)) {
    173 		filename = "stdout";
    174 		error(strerror(errno));
    175 	}
    176 
    177 	return status;
    178 }