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
       ---
       ranlib.c (5885B)
       ---
            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)) < 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);
          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 }