scc

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

ranlib.c (5177B)


      1 #include <ctype.h>
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stdarg.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <time.h>
      9 
     10 #include <scc/ar.h>
     11 #include <scc/arg.h>
     12 #include <scc/mach.h>
     13 #include <scc/scc.h>
     14 
     15 #include "sys.h"
     16 
     17 #define NR_SYMDEF 32
     18 
     19 static char *namidx;
     20 static long nsymbols;
     21 static int status, artype, nolib;
     22 static char *filename, *membname;
     23 static Objsymdef *htab[NR_SYMDEF], *head;
     24 static long offset;
     25 char *argv0;
     26 
     27 static char *
     28 errstr(void)
     29 {
     30 	return strerror(errno);
     31 }
     32 
     33 static void
     34 error(char *fmt, ...)
     35 {
     36 	va_list va;
     37 
     38 	va_start(va, fmt);
     39 	fprintf(stderr, "ranlib: %s: ", filename);
     40 	if (membname)
     41 		fprintf(stderr, "%s: ", membname);
     42 	vfprintf(stderr, fmt, va);
     43 	putc('\n', stderr);
     44 	va_end(va);
     45 
     46 	status = EXIT_FAILURE;
     47 }
     48 
     49 Objsymdef *
     50 lookup(char *name)
     51 {
     52 	unsigned h;
     53 	Objsymdef *dp;
     54 	char *s;
     55 	size_t len;
     56 
     57 	h = genhash(name) % NR_SYMDEF;
     58 
     59 	for (dp = htab[h]; dp; dp = dp->next) {
     60 		if (!strcmp(dp->name, name))
     61 			return dp;
     62 	}
     63 
     64 	len = strlen(name) + 1;
     65 	dp = malloc(sizeof(*dp));
     66 	s = malloc(len);
     67 	if (!dp || !s) {
     68 		free(s);
     69 		free(dp);
     70 		return NULL;
     71 	}
     72 
     73 	nsymbols++;
     74 	dp->name = s;
     75 	memcpy(dp->name, name, len);
     76 	dp->type = 'U';
     77 	dp->offset = -1;
     78 	dp->hash = htab[h];
     79 	htab[h] = dp;
     80 	dp->next = head;
     81 	head = dp;
     82 
     83 	return dp;
     84 }
     85 
     86 static int
     87 newsymbol(Objsym *sym)
     88 {
     89 	Objsymdef *np;
     90 
     91 	if (!isupper(sym->type) || sym->type == 'N')
     92 		return 1;
     93 
     94 	if ((np = lookup(sym->name)) == NULL) {
     95 		error("out of memory");
     96 		return 0;
     97 	}
     98 
     99 	switch (np->type) {
    100 	case 'C':
    101 		if (sym->type == 'C')
    102 			break;
    103 	case 'U':
    104 		np->type = sym->type;
    105 		np->offset = offset;
    106 		break;
    107 	default:
    108 		if (sym->type != 'C') {
    109 			error("multiple definitions of '%s'", sym->name);
    110 			return 0;
    111 		}
    112 	}
    113 
    114 	return 1;
    115 }
    116 
    117 static int
    118 newmember(FILE *fp, char *nam, void *data)
    119 {
    120 
    121 	int t, ret = 0;
    122 	Obj *obj;
    123 	Objsym *sym;
    124 
    125 	if (artype == -1 && (!strcmp(nam, "/") || !strcmp(nam, "__.SYMDEF")))
    126 		return 1;
    127 
    128 	membname = nam;
    129 	offset = ftell(fp);
    130 
    131 	if (offset == EOF) {
    132 		error(errstr());
    133 		return 0;
    134 	}
    135 
    136 	t = objtype(fp, NULL);
    137 	if (t == -1 || artype != -1 && artype != t) {
    138 		nolib = 1;
    139 		return 0;
    140 	}
    141 	artype = t;
    142 
    143 	if ((obj = objnew(t)) == NULL) {
    144 		error("out of memory");
    145 		return 0;
    146 	}
    147 	namidx = obj->index;
    148 
    149 	if (objread(obj, fp) < 0 || objsyms(obj) < 0) {
    150 		error("file corrupted");
    151 		goto error;
    152 	}
    153 
    154 	for (sym = obj->syms; sym; sym = sym->next) {
    155 		if (!newsymbol(sym))
    156 			goto error;
    157 	}
    158 
    159 	ret = 1;
    160 
    161 error:
    162 	objdel(obj);
    163 	return ret;
    164 }
    165 
    166 static void
    167 freehash(void)
    168 {
    169 	Objsymdef **npp, *next, *np;
    170 
    171 	for (npp = htab; npp < &htab[NR_SYMDEF]; npp++)
    172 		*npp = NULL;
    173 
    174 	for (np = head; np; np = next) {
    175 		next = np->next;
    176 		free(np->name);
    177 		free(np);
    178 	}
    179 
    180 	head = NULL;
    181 }
    182 
    183 static int
    184 readsyms(FILE *fp)
    185 {
    186 	if (!archive(fp)) {
    187 		error("file format not recognized");
    188 		return 0;
    189 	}
    190 
    191 	if (formember(fp, newmember, NULL) < 0) {
    192 		error("library file corrupted");
    193 		return 0;
    194 	}
    195 
    196 	return 1;
    197 }
    198 
    199 static int
    200 merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx)
    201 {
    202 	int c;
    203 	char mtime[13];
    204 	struct ar_hdr first;
    205 
    206 	rewind(lib);
    207 	rewind(idx);
    208 	fseek(lib, SARMAG, SEEK_SET);
    209 
    210 	if (fread(&first, sizeof(first), 1, lib) != 1)
    211 		return 0;
    212 
    213 	if (!strncmp(first.ar_name, namidx, SARNAM))
    214 		fseek(lib, atol(first.ar_size), SEEK_CUR);
    215 	else
    216 		fseek(lib, SARMAG, SEEK_SET);
    217 
    218 	fwrite(ARMAG, SARMAG, 1, to);
    219 
    220         strftime(mtime, sizeof(mtime), "%s", gmtime(&prop->time));
    221         fprintf(to,
    222                 "%-16.16s%-12s%-6u%-6u%-8lo%-10ld`\n",
    223                 namidx,
    224                 mtime,
    225                 prop->uid,
    226                 prop->gid,
    227                 prop->mode,
    228                 prop->size);
    229 
    230 	while ((c = getc(idx)) != EOF)
    231 		putc(c, to);
    232 	if (prop->size & 1)
    233 		putc('\n', to);
    234 
    235 	while ((c = getc(lib)) != EOF)
    236 		putc(c, to);
    237 
    238 	fflush(to);
    239 
    240 	if (ferror(to) || ferror(lib) || ferror(idx))
    241 		return 0;
    242 
    243 	return 1;
    244 }
    245 
    246 static int
    247 copy(FILE *from, char *fname)
    248 {
    249 	int c, ret;
    250 	FILE *fp;
    251 
    252 	if ((fp = fopen(fname, "wb")) == NULL)
    253 		return 0;
    254 
    255 	rewind(from);
    256 	while ((c = getc(from)) != EOF)
    257 		putc(c, fp);
    258 	fflush(fp);
    259 
    260 	ret = !ferror(fp) && !ferror(from);
    261 
    262 	fclose(fp);
    263 
    264 	return ret;
    265 }
    266 
    267 static void
    268 ranlib(char *fname)
    269 {
    270 	int c;
    271 	FILE *fp, *idx, *out;
    272 	long siz;
    273 	struct fprop prop;
    274 
    275 	errno = 0;
    276 	nolib = 0;
    277 	artype = -1;
    278 	nsymbols = 0;
    279 	filename = fname;
    280 	freehash();
    281 
    282 	fp = fopen(fname, "rb");
    283 	idx = tmpfile();
    284 	out = tmpfile();
    285 	if (!fp || !idx || !out)
    286 		goto error;
    287 
    288 	if (!readsyms(fp))
    289 		goto error;
    290 
    291 	if (nolib)
    292 		goto error;
    293 
    294 	siz = setindex(artype, nsymbols, head, idx);
    295 	if (siz <= 0)
    296 		goto error;
    297 
    298 	if (getstat(fname, &prop) < 0)
    299 		goto error;
    300 	prop.size = siz;
    301 	prop.time = time(NULL);
    302 
    303 	if (!merge(out, &prop, fp, idx))
    304 		goto error;
    305 
    306 	fclose(fp);
    307 	fclose(idx);
    308 	fp = idx = NULL;
    309 
    310 	if (!copy(out, fname))
    311 		goto error;
    312 
    313 	fclose(out);
    314 
    315 	return;
    316 
    317 error:
    318 	if (errno)
    319 		error(errstr());
    320 	if (idx)
    321 		fclose(idx);
    322 	if (out)
    323 		fclose(out);
    324 	if (fp)
    325 		fclose(fp);
    326 }
    327 
    328 static void
    329 usage(void)
    330 {
    331 	fputs("usage: ranlib [-t] file...\n", stderr);
    332 	exit(EXIT_FAILURE);
    333 }
    334 
    335 int
    336 main(int argc, char *argv[])
    337 {
    338 	ARGBEGIN {
    339 	case 't':
    340 		break;
    341 	default:
    342 		usage();
    343 	} ARGEND
    344 
    345 	if (argc == 0)
    346 		usage();
    347 
    348 	for (; *argv; ++argv)
    349 		ranlib(*argv);
    350 
    351 	return status;
    352 }