#ifndef lint
static char sccsid[] = "%W% (UKC) %G%";
#endif  lint
/***

* program name:
	nlist
* function:
	display namelist of object file as text
* syntax:
	selex file.o ...
* history:
	March 85	Selex written by Martin Guy, UKC.
	October 85	Selex ported to 4.1 Orion Unix
	September 86	Nlist hacked up from selex
***/

#include <stdio.h>
#include <a.out.h>

char *malloc();

char *progname;

main(argc, argv)
char **argv;
{
	register int i;

	progname = argv[0];

	if (argc < 2) {
		process(0, "stdin");
	} else for (i=1; i<argc; i++) {
		int fd;

		fd = open(argv[i], 0);
		if (fd < 0) {
			fprintf(stderr, "%s: Cannot open \"%s\".\n", progname, argv[i]);
		} else {
			puts(argv[i]);
			process(fd, argv[1]);
			(void) close(fd);
		}
	}
	exit(0);
}

static char ntypechar[] = {
	'u',	'U',	'a',	'A',	't',	'T',	'd',	'D',
	'b',	'B',	'c',	'C',	'?',	'?',	'?',	'?',
	'?',	'?',	'?',	'?',	'?',	'?',	'?',	'?',
	'?',	'?',	'?',	'?',	'?',	'?',	'?',	'f',
};

process(fd, name)
int fd;
char *name;
{
	register int i;
	struct exec header;	/* a.out file header */
	struct nlist symbol;	/* buffer for symbol being examined */
	int	nsyms;		/* number of symbols in symbol table */
	char *	strtab;		/* the string table */
	long	strtabsize;	/* size of string table */

	/* Read in header */

	if (read(fd, (char *)&header, sizeof(header)) != sizeof(header)) {
		fprintf(stderr, "%s: Read fails to get header of object file.\n", progname);
		perror(progname);
		exit(1);
	}

	/* check magic number */

	if (N_BADMAG(header)) {
		fprintf (stderr, "%s: \"%s\" is not an object file.\n", progname, name);
		exit(1);
	}

	/* read in string table in one gulp */

	if (lseek(fd, N_STROFF(header), 0) < 0) {
		char buf[64];
		perror(sprintf(buf, "%s: Error seeking to string table from \"%s\"", progname, name));
		exit(1);
	}

	/* sizeof(strtabsize) is defined to be 4. */
	if (read(fd, (char *)&strtabsize, 4) != sizeof(strtabsize)) {
		char buf[64];
		perror(sprintf(buf, "%s: Error reading string table size from \"%s\"", progname, name));
		exit(1);
	}

	strtab = malloc((unsigned) strtabsize);
	if (strtab == NULL) {
		fprintf(stderr, "%s: Out of memory.\n", progname);
		exit(1);
	}
	if (read (fd, strtab+4, strtabsize-4) != strtabsize-4) {
		char buf[64];
		perror(sprintf(buf, "%s: Error reading string table size from \"%s\"", progname, name));
		exit(1);
	}

	/* Now run through the symbols */
	if (header.a_syms % sizeof(struct nlist) != 0) {
		fprintf(stderr, "%s: Corrupt object file\n.", progname);
		exit(1);
	}
	nsyms = header.a_syms / sizeof(struct nlist);
	lseek(fd, N_SYMOFF(header), 0);
	for (i=0; i<nsyms; i++) {
		read(fd, (char *)&symbol, sizeof(symbol));
		printf("%-15s %8d %c %d\n",
			&(strtab[symbol.n_un.n_strx]),
			symbol.n_type,
			ntypechar[symbol.n_type & (N_TYPE | N_EXT)],
			symbol.n_value);
	}
	exit(0);
}
