ref: 6f15bbc2f063296165f0a3ae742c671a828a0297
parent: c50958a29245fe95b6f22473bfcc17f0cf5e3025
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Jan 8 09:47:18 EST 2019
[ranlib] Add first version of ranlib This version is not functional yet
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -7,6 +7,7 @@
$(BINDIR)/strip \
$(BINDIR)/size \
$(BINDIR)/ar \
+ $(BINDIR)/ranlib \
LIBS = -lmach
@@ -22,6 +23,9 @@
$(BINDIR)/size: size.o
$(CC) $(SCC_LDFLAGS) size.o -lmach -o $@
+
+$(BINDIR)/ranlib: ranlib.o
+ $(CC) $(SCC_LDFLAGS) ranlib.o -lmach -o $@
$(BINDIR)/ar: ar.o ar-$(DRIVER).o
$(CC) $(SCC_LDFLAGS) ar.o ar-$(DRIVER).o -o $@
--- /dev/null
+++ b/src/cmd/ranlib.c
@@ -1,0 +1,276 @@
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/arg.h>
+#include <scc/mach.h>
+
+#define NR_NAMES 32
+
+typedef struct name Name;
+
+struct name {+ char *name;
+ int type;
+ long offset;
+ Name *hash, *next;
+};
+
+static int status;
+static char *filename, *membname;
+static Name *htab[NR_NAMES], *head;
+static long offset;
+char *argv0;
+
+static void
+error(char *fmt, ...)
+{+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stderr, "ranlib: %s: ", filename);
+ if (membname)
+ fprintf(stderr, "%s: ", membname);
+ vfprintf(stderr, fmt, va);
+ putc('\n', stderr);+ va_end(va);
+
+ status = EXIT_FAILURE;
+}
+
+Name *
+lookup(char *name)
+{+ unsigned h;
+ Name *np;
+ char *s;
+ size_t len;
+
+ h = 0;
+ for (s = name; *s; s++)
+ h += *s;
+ h %= NR_NAMES;
+
+ for (np = htab[h]; np; np = np->next) {+ if (!strcmp(np->name, name))
+ return np;
+ }
+
+ len = strlen(name) + 1;
+ np = malloc(sizeof(*np));
+ s = malloc(len);
+ if (!np || !s) {+ free(s);
+ free(np);
+ return NULL;
+ }
+
+ memcpy(np->name, s, len);
+ np->type = 'U';
+ np->offset = -1;
+ np->hash = htab[h];
+ htab[h] = np;
+ np->next = head;
+ head = np;
+
+ return np;
+}
+
+static int
+newsymbol(Symbol *sym, void *data)
+{+ Name *np;
+
+ if (!isupper(sym->type))
+ return 1;
+
+ if ((np = lookup(sym->name)) == NULL) {+ error("out of memory");+ return 0;
+ }
+
+ switch (np->type) {+ case 'C':
+ if (sym->type == 'C')
+ break;
+ case 'U':
+ np->type = sym->type;
+ np->offset = offset;
+ break;
+ default:
+ if (sym->type != 'C') {+ error("multiple definitions of '%s'", sym->name);+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int
+newmember(FILE *fp, char *name, void *data)
+{+
+ int t, ret = 0;
+ Obj *obj;
+
+ membname = name;
+ offset = ftell(fp);
+
+ if (offset == EOF) {+ error(strerror(errno));
+ return 0;
+ }
+
+ if ((t = objtype(fp, NULL)) == -1)
+ return 1;
+
+ if ((obj = objnew(t)) == NULL) {+ error("out of memory");+ return 0;
+ }
+
+ if (objread(obj, fp) < 0) {+ error("file corrupted");+ goto error;
+ }
+
+ if (!objtraverse(obj, newsymbol, NULL)) {+ error("traversing object file");+ goto error;
+ }
+
+ ret = 1;
+
+error:
+ objdel(obj);
+ return ret;
+}
+
+static void
+freenames(void)
+{+ Name **npp, *next, *np;
+
+ for (npp = htab; npp < &htab[NR_NAMES]; npp++)
+ *npp = NULL;
+
+ for (np = head; np; np = next) {+ next = np->next;
+ free(np->name);
+ free(np);
+ }
+
+ head = NULL;
+}
+
+static int
+readsyms(char *fname)
+{+ FILE *fp;
+
+ if ((fp = fopen(fname, "rb")) == NULL) {+ error(strerror(errno));
+ goto error;
+ }
+
+ if (!archive(fp)) {+ error("file format not recognized");+ goto error;
+ }
+
+ if (!artraverse(fp, newmember, NULL)) {+ error("while traversing archive");+ goto error;
+ }
+
+ if (fclose(fp)) {+ error(strerror(errno));
+ return 0;
+ }
+ return 1;
+
+error:
+ fclose(fp);
+ return 0;
+}
+
+static int
+writeidx(char *fname)
+{+ int r;
+ FILE *fp;
+ Name *np;
+
+ if ((fp = fopen(fname, "wb")) == NULL) {+ error("index file: %s", strerror(errno));+ return 0;
+ }
+
+ for (np = head; np; np = np->next) {+ /* TODO: write out */
+ }
+ fflush(fp);
+ r = ferror(fp);
+ fclose(fp);
+
+ if (!r)
+ return 1;
+
+ error("index file: %s", strerror(errno));+ return 0;
+}
+
+static int
+insertidx(char *archive, char *idx)
+{+ return 0;
+}
+
+static void
+ranlib(char *fname)
+{+ static char symdef[] = "__.SYMDEF";
+
+ filename = fname;
+ freenames();
+
+ if (!readsyms(fname))
+ return;
+
+ if (!writeidx(symdef))
+ return;
+
+ if (!insertidx(fname, symdef))
+ remove(symdef);
+
+ return;
+}
+
+static void
+usage(void)
+{+ fputs("usage: ranlib [file...]\n", stderr);+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{+ ARGBEGIN {+ default:
+ usage();
+ } ARGEND
+
+ if (argc == 0) {+ ranlib("a.out");+ } else {+ for (; *argv; ++argv)
+ ranlib(*argv);
+ }
+
+ return status;
+}
--
⑨