scc

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

size.c (2844B)


      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 n, i;;
     43 	Obj *obj;
     44 	unsigned long long total, *p;
     45 	Objsect *secp;
     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) {
     54 		error("file corrupted");
     55 		goto err1;
     56 	}
     57 
     58 	siz.text = siz.data = siz.bss = 0;
     59 	if ((n = objsect(obj, &secp)) < 0) {
     60 		error("out of memory");
     61 		goto err1;
     62 	}
     63 
     64 	for (i = 0; i < n; i++) {
     65 		switch (secp[i].type) {
     66 		case 'T':
     67 			p = &siz.text;
     68 			break;
     69 		case 'D':
     70 			p = &siz.data;
     71 			break;
     72 		case 'B':
     73 			p = &siz.bss;
     74 			break;
     75 		default:
     76 			continue;
     77 		}
     78 
     79 		if (*p > ULLONG_MAX - secp->size) {
     80 			error("integer overflow");
     81 			goto err2;
     82 		}
     83 			
     84 		*p += secp->size;
     85 	}
     86 
     87 	total = siz.text + siz.data + siz.bss;
     88 	printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
     89 	       siz.text,
     90 	       siz.data,
     91 	       siz.bss,
     92 	       total, total, filename);
     93 
     94 	ttext += siz.text;
     95 	tdata += siz.data;
     96 	tbss += siz.bss;
     97 	ttotal += total;
     98 
     99 err2:
    100 	free(secp);
    101 err1:
    102 	objdel(obj);
    103 }
    104 
    105 static int
    106 newmember(FILE *fp, char *name, void *data)
    107 {
    108 	int t;
    109 
    110 	membname = name;
    111 	if ((t = objtype(fp, NULL)) != -1)
    112 		newobject(fp, t);
    113 
    114 	return 1;
    115 }
    116 
    117 static void
    118 size(char *fname)
    119 {
    120 	int t;
    121 	FILE *fp;
    122 
    123 	filename = fname;
    124 	if ((fp = fopen(fname, "rb")) == NULL) {
    125 		error(strerror(errno));
    126 		return;
    127 	}
    128 
    129 	if ((t = objtype(fp, NULL)) != -1) {
    130 		newobject(fp, t);
    131 	} else if (archive(fp)) {
    132 		if (formember(fp, newmember, NULL) < 0)
    133 			error("library corrupted");
    134 	} else {
    135 		error("bad format");
    136 	}
    137 
    138 	if (ferror(fp))
    139 		error(strerror(errno));
    140 
    141 	fclose(fp);
    142 }
    143 
    144 static void
    145 usage(void)
    146 {
    147 	fputs("usage: size [-t] [file...]\n", stderr);
    148 	exit(EXIT_FAILURE);
    149 }
    150 
    151 int
    152 main(int argc, char *argv[])
    153 {
    154 	unsigned long long total;
    155 
    156 	ARGBEGIN {
    157 	case 't':
    158 		tflag = 1;
    159 		break;
    160 	default:
    161 		usage();
    162 	} ARGEND
    163 
    164 	puts("text\tdata\tbss\tdec\thex\tfilename");
    165 
    166 	if (argc == 0) {
    167 		size("a.out");
    168 	} else {
    169 		for (; *argv; ++argv)
    170 			size(*argv);
    171 	}
    172 
    173 	if (tflag) {
    174 		total = ttext + tdata + tbss;
    175 		printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
    176 		       ttext, tdata, tbss, total, total, "(TOTALS)");
    177 	}
    178 
    179 	if (fflush(stdout)) {
    180 		filename = "stdout";
    181 		error(strerror(errno));
    182 	}
    183 
    184 	return status;
    185 }