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;
+}