[net.micro.6809] Microware C lorder program

jejones@ea.UUCP (11/17/84)

The following (not a shell archive, since it's only one file) is a
program that does for Microware C relocatable and library files what
lorder(1) does for Unix .o files.

The following brash one-liner makes fun of condescending Unix
documentation: "Take my wife--please!"

In conjunction with previously posted stuff (LibSplit), I'm going to
use this to shuffle the Microware C library, clib.l, to see if it makes
any difference in speed of compilation. If it helps, I'll let you
know.

BTW--I know I took the sleazy way out on looking for duplications in
ShowDep(). I probably should have kept a high-water mark on ECount
and allocated that much (it's just a one-shot anyway). Sigh...

					James Jones

------------------------------TARE HEAR------------------------------
/*
 * LOrder -- display dependencies among pieces of relocatable and 
 *	library files
 *
 * usage: LOrder <pathname> [<pathname> ...]
 *
 * semantics: LOrder reads the specified files and looks at the
 *	global symbols used and defined by the parts thereof. It
 *	then writes to standard output a sequence of lines of the
 *	form "m1 m2," where m1 is the name of a "module" that refers
 *	to a global symbol defined in the "module" m2.
 */

#include <stdio.h>

#define ROFSYNC	0x62cd2387	/* ROF "sync bytes" */
				/* ("magic number" to Unixoids) */
#define SYMLEN	9		/* maximum symbol length */
#define MAXNAME	16		/* maximum "module" name length */
#define HASHSIZE	151	/* size of symbol hash table */
#define MODULE	1		/* tag for "modules"		*/
#define GLOBAL	0		/* and for globals		*/
#define MAXREFS	40	/* arbitrary bound on external references */

/* definition/reference */

typedef struct {
	char		r_flag;	/* type/location */
	unsigned	r_offset;
} def_ref;

/* "module" header structure */

typedef struct {
	long		h_sync;		/* should == ROFSYNC */
	unsigned	h_tylan;	/* type/language/attr/revision */
	char		h_valid;	/* asm valid? */
	char		h_date[5];	/* creation date */
	char		h_edit;		/* edition # */
	char		h_spare;
					/* next, sizes of: */
	unsigned	h_glbl,		/* globals */
			h_dglbl,	/* direct page globals */
			h_data,		/* data */
			h_ddata,	/* direct page data */
			h_ocode;	/* code */
	unsigned	h_stack,
			h_entry;
}	binhead;

/* what we keep track of for symbols */

typedef struct module {
	char		m_name[MAXNAME];
	struct global	**ref_list;
	struct module	*m_next;
} Module;
typedef struct global {
	char		s_name[MAXNAME];
	struct module	*def_by;
	struct global	*s_next;
} Global;

binhead	header;
FILE	*LibFP;
Global	*HashTable[HASHSIZE];
Module	*MList;

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

	if (argc < 2) {
		fprintf(stderr, "usage: LOrder pathname [pathname ...]\n");
		exit(1);
	}

	MList = NULL;
	for (i = 0; i < HASHSIZE; i++)
		HashTable[i] = NULL;

	for (i = 1; i < argc; i++)
		DoLibFile(argv[i]);

	ShowDep();

}

DoLibFile(LibPath)
char	*LibPath;
{
	Module	*NewMod, *GetModule();

	if ((LibFP = fopen(LibPath, "r")) == NULL) {
		fprintf(stderr, "LOrder: can't open %s\n", LibPath);
		exit(1);
	}

	while (fread(&header, sizeof(header), 1, LibFP) > 0) {
		if (header.h_sync != ROFSYNC) {
			fprintf(stderr, "%s is not a library file\n", LibPath);
			exit(1);
		}
		NewMod = GetModule();
		DoGlobalDefs(NewMod);
		fseek(LibFP,
			(long) header.h_ocode + header.h_ddata + header.h_data,
			1);
		DoExtRefs(NewMod);
		SkipRefs();	/* local references */
	}

	fclose(LibFP);

}

DoGlobalDefs(Mod)
Module	*Mod;
{
	int	GCount;
	Global	*GSym, *GetGlobal();

	GCount = getw(LibFP);

	for (; GCount > 0; GCount--) {
		GSym = GetGlobal();
		GSym->def_by = Mod;
		fseek(LibFP, (long)(sizeof(char) + sizeof(int)), 1);
	}

}

DoExtRefs(Mod)
Module	*Mod;
{
	int	i, ECount;
	Global	*GetGlobal(), **rlist;

	ECount = getw(LibFP);


	rlist = calloc(ECount + 1, sizeof(Global *));
	if (rlist == NULL) {
		exit(1);
	}
	Mod->ref_list = rlist;

	for (i = 0; i < ECount; i++) {
		rlist[i] = GetGlobal();
		SkipRefs();
	}

}

SkipRefs()
{
	int	RCount;

	RCount = getw(LibFP);
	fseek(LibFP, (long) (RCount * sizeof(def_ref)), 1);

}

Global *
GetGlobal()
{
	char	NameIn[MAXNAME];
	Global	*NewGlob;
	int	i, hash;

	for (i = 0; NameIn[i] = getc(LibFP); i++)
		;

	for (hash = i = 0; NameIn[i]; i++)
		hash ^= NameIn[i] << (i & 7);
	hash = hash % HASHSIZE;

	for (NewGlob = HashTable[hash]; NewGlob != NULL; ) {
		if (strcmp(NameIn, NewGlob->s_name) == 0) {
			return(NewGlob);
		}
		NewGlob = NewGlob->s_next;
	}

	if ((NewGlob = malloc(sizeof(Global))) == NULL) {
		fprintf(stderr, "LOrder: out of memory\n");
		exit(1);
	}
	strcpy(NewGlob->s_name, NameIn);
	NewGlob->def_by = NULL;
	NewGlob->s_next = HashTable[hash];
	HashTable[hash] = NewGlob;
	return(NewGlob);

}

Module *
GetModule()
{
	Module	*NewMod;
	char	*scan;

	if ((NewMod = malloc(sizeof(Module))) == NULL) {
		fprintf(stderr, "LOrder: out of memory\n");
		exit(1);
	}
	for (scan = NewMod->m_name; *scan = getc(LibFP); scan++)
		;
	NewMod->ref_list = NULL;
	NewMod->m_next = MList;
	MList = NewMod;
	return(NewMod);

}

ShowDep()
{
	int	i, j, rcount;
	Global	**rlist;
	Module	*scan, *deplist[MAXREFS];

	for (scan = MList; scan != NULL; scan = scan->m_next) {
		rcount = 0;
		rlist = scan->ref_list;
		for (i = 0; rlist[i] != NULL; i++) {
			if ((rlist[i])->def_by == NULL)
				fprintf(stderr, "LOrder: %s is not defined\n",
					(rlist[i])->s_name);
			else {
				deplist[rcount] = (rlist[i])->def_by;
				for (j = 0;
					deplist[j] != deplist[rcount];
					j++)	;
				if (j >= rcount)
					rcount++;
			}
		}
		for (j = 0; j < rcount; j++)
			printf("%s %s\n", scan->m_name, deplist[j]->m_name);
	}

}