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