[comp.sources.amiga] v90i173: ADLookUp - look up functions in the on-line autodocs, Part01/01

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/04/90)

Submitted-by: caw@miroc.Chi.IL.US (Christopher A. Wichura)
Posting-number: Volume 90, Issue 173
Archive-name: util/adlookup/part01

This is a program similar to GetAutoDoc found in P. Cherna's DevKit
package.  It does the same thing, looks up functions in on-line autodocs,
but does a slightly better job of it (IMHO).  It performs index searches
much faster and has support for multiuple occurances of the same function.


#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  ADBIstartup.a ADBuildIndex.c ADLUstartup.a ADLookUp.c
#   LibText1.txt LibText2.txt LibText3.txt lmkfile readme
# Wrapped by tadguy@xanth on Sun Jun  3 18:40:20 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ADBIstartup.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ADBIstartup.a'\"
else
echo shar: Extracting \"'ADBIstartup.a'\" \(2507 characters\)
sed "s/^X//" >'ADBIstartup.a' <<'END_OF_FILE'
X INCLUDE "libraries/ArpBase.i"
X INCLUDE "exec/execbase.i"
X INCLUDE "libraries/dosextens.i"
X
X XREF _main
X XREF _DOSBase
X
X XREF _LVOOpenLibrary
X XREF _LVOCloseLibrary
X XREF _LVOSetSignal
X XREF _LVOForbid
X XREF _LVOWaitPort
X XREF _LVOGetMsg
X XREF _LVOReplyMsg
X
X XREF _LinkerDB
X XREF __BSSBAS
X XREF __BSSLEN
X XREF _RESLEN
X XREF _RESBASE
X XREF _NEWDATAL
X
XCALL	MACRO
X	jsr _LVO\1(a6)
X	ENDM
X
X  SECTION StartCode,CODE
X
X; arp resident tag goes here
X	RESIDENT 4*1024
X
Xinit:
X	movem.l	d0/a0,-(sp)
X	lea	_LinkerDB,a4
X	movea.l	4,a6
X	lea	ARPlib(pc),a1
X	moveq	#39,d0
X	CALL	OpenLibrary
X	tst.l	d0
X	bne.s	__main
X
X	lea	DOSlib(pc),a1
X	CALL	OpenLibrary
X	tst.l	d0
X	beq.s	bomb
X
X	move.l	d0,a6
X	CALL	Output
X	move.l	d0,d1
X	beq.s	bomb
X
X	lea	Msg1(pc),a0
X	move.l	a0,d2
X	moveq	#Msg1Len,d3
X	CALL	Write
X
X	move.l	a6,a1
X	movea.l	4,a6
X	CALL	CloseLibrary
X	moveq	#0,d0
X
Xbomb:
X	addq.l	#8,sp
X	rts
X
XDOSlib	dc.b "dos.library",0
X
XMsg1	dc.b "You need "
XARPlib	dc.b "arp.library",0
X	dc.b " V39+",10,0
XMsg1Len	EQU *-Msg1
X	ds.w 0
X
X__main:
X	move.l	d0,a6
X	sub.l	#_RESBASE,a4
X
X; get mem to hold data and bss stuff
X	move.l	#_RESLEN,d0
X	CALL	ArpAlloc
X	tst.l	d0
X	bne.s	gotmem
X
X	moveq	#20,d0
X	moveq	#0,d2
X	CALL	ArpExit
X
X; get ready to copy data over into freshly alloced data area
Xgotmem:	move.l	d0,a0
X	move.l	d0,a2
X
X	move.l	d0,a1
X	move.l	#_NEWDATAL,d0
Xcpy:	move.l	(a4)+,(a0)+
X	subq.l	#1,d0
X	bne.s	cpy
X
X; now do the relocs for resident data
X	move.l	(a4)+,d0
Xreloc:	beq.s	nreloc
X	move.l	a1,a0
X	add.l	(a4)+,a0
X	add.l	(a0),a2
X	move.l	a2,(a0)
X	move.l	a1,a2
X	subq.l	#1,d0
X	bra.s	reloc
X
Xnreloc:	move.l	a1,a4
X	add.l	#_RESBASE,a4
X
X; stash some important junk away
X	move.l	a6,_ArpBase(a4)
X	move.l	DosBase(a6),_DOSBase(a4)
X	movea.l	4,a6
X	move.l	a6,_SysBase(a4)
X	movem.l	sp,__StackPtr(a4)
X
X; get address of our task
X	move.l	ThisTask(a6),a3
X
X; clear any pending signals
X	moveq	#0,d0
X	move.l	#$00003000,d1
X	CALL	SetSignal
X
X; check for workbench and exit fast if so
X	tst.l	pr_CLI(a3)
X	bne.s	FromCLI
X
X	lea	pr_MsgPort(a3),a0
X	CALL	WaitPort
X	lea	pr_MsgPort(a3),a0
X	CALL	GetMsg
X	move.l	d0,d2
X	beq.s	ExitToDOS
X
X	CALL	Forbid
X	movea.l	d2,a1
X	CALL	ReplyMsg
X	moveq	#0,d0
X	bra.s	ExitToDOS
X
XFromCLI:
X	movem.l	(sp)+,d0/a0
X	jsr	_main
X	moveq.l	#0,d0
X	bra.s	ExitToDOS
X
X XDEF _XCEXIT
X_XCEXIT:
X	move.l	4(sp),d0
X XDEF @XCEXIT
X@XCEXIT:
X
XExitToDOS:
X	move.l	_ArpBase(a4),a6
X	movea.l	__StackPtr(a4),sp
X	moveq	#0,d2
X	CALL	ArpExit
X
X; ---- This is a data section
X
X   SECTION __MERGED,BSS
X
X XDEF _ArpBase
X XDEF _SysBase
X XDEF __StackPtr
X
X_ArpBase    ds.b 4
X_SysBase    ds.b 4
X__StackPtr  ds.b 4
X
X   END
END_OF_FILE
if test 2507 -ne `wc -c <'ADBIstartup.a'`; then
    echo shar: \"'ADBIstartup.a'\" unpacked with wrong size!
fi
# end of 'ADBIstartup.a'
fi
if test -f 'ADBuildIndex.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ADBuildIndex.c'\"
else
echo shar: Extracting \"'ADBuildIndex.c'\" \(20082 characters\)
sed "s/^X//" >'ADBuildIndex.c' <<'END_OF_FILE'
X/*	ADBuildIndex.c
X	(c) 1989 by Christopher A. Wichura (u12401@uicvm.uic.edu)
X
X	Created: 12/19/89
X
X	Compile with:  LC -d2 -v -cs -rr ADBuildIndex
X*/
X
X#include <exec/types.h>
X#include <libraries/ArpBase.h>
X#include <proto/dos.h>
X
X/* here we have the structures that will be used to hold index entries */
Xstruct IndexData {
X	char *id_Func;
X	char *id_Lib;
X	char *id_Path;
X	char *id_File;
X	unsigned long id_Offset;
X};
X
Xstruct NextIndexNode {
X	struct NextIndexNode *nin_Next;
X	struct IndexData nin_IndexData;
X};
X
Xstruct FullIndexNode {
X	struct FullIndexNode *fin_Greater;
X	struct FullIndexNode *fin_Lesser;
X	struct NextIndexNode *fin_Next;
X	struct IndexData fin_IndexData;
X};
X
Xstruct IndexNodeNumbered {
X	unsigned long inn_Num;
X	struct IndexNodeNumbered *inn_Parent;
X	struct IndexNodeNumbered *inn_Greater;
X	struct IndexNodeNumbered *inn_Lesser;
X	struct NextIndexNode *inn_Next;
X	struct IndexData inn_IndexData;
X};
X
X/* this structure will be used when building name lists.  Note that the
X   text field is not actually 2 bytes long, but rather will be allocated to
X   the size of the text to be stored when the node is created */
Xstruct TextNode {
X	struct TextNode *tn_Next;
X	char tn_Text[2];
X};
X
X/* here we have some globals that hold the bases of the various lists we
X   will be building */
Xunsigned long Indexs = 0;	/* total number of index nodes */
Xstruct IndexNodeNumbered *FirstIndex = NULL;
Xstruct TextNode *FirstFunc = NULL;
Xstruct TextNode *FirstLib  = NULL;
Xstruct TextNode *FirstPath = NULL;
Xstruct TextNode *FirstFile = NULL;
X
X/* externs to our three text chunks */
Xextern char __far LibText1[];
Xextern char __far LibText2[];
Xextern char __far LibText3[];
X
X/* we will need to be able to tell what our current position is within a
X   given file.  However, we will be doing buffered IO as well so we need an
X   easy way to get this info.  result is a global variable that the
X   io routine will update for us. */
Xunsigned long CurrOffset;
X
X/* our main buffer pointer will also be made global */
Xchar *MainBuf;
X
X/* the parsed pattern will be stored in a global buffer as well */
Xchar Pattern[10];
X
X/* we will store the current date and time strings in globals, also */
Xstruct DateTime dat;
Xchar Date[LEN_DATSTRING];
Xchar Time[LEN_DATSTRING];
X
X/* if this flag is set then we give a verbose report as we go along */
XBOOL Vflag;
X
X/* if this flag is set then don't expand to full pathnames */
XBOOL Eflag;
X
X/* we need to make a ResList global so that when we call AddIndex and
X   AddTextNode they don't allocate their memory into the nested ResList
X   that is created, thus losing their info right away */
Xstruct ResList *MainRes;
X
X/* we will make our outhandle global as well */
XBPTR OutHandle;
X
X/* here we prototype routines used in this file */
X#define strcpy __builtin_strcpy
X#define strlen __builtin_strlen
X
Xvoid Msg(char *);
Xvoid XCEXIT(int);
Xvoid NoMem(void);
Xvoid ChkAbt(void);
Xint  GetChar(BPTR);
Xvoid GetLine(BPTR);
Xvoid DoDir(char *);
Xint  strlen(char *);
Xvoid WriteIndex(void);
Xvoid DoFirstDir(char *);
Xvoid WriteIndexNodes(void);
Xvoid strcpy(char *, char *);
Xint  stricmp(char *, char *);
Xvoid ProcessFile(BPTR, char *, char *);
Xvoid WriteTextList(char *, struct TextNode *);
Xint  Compare(char *, char *, struct TrxtNode *);
Xint  WriteIndexTree(struct IndexNodeNumbered *);
Xint  WriteNextNodes(struct IndexNodeNumbered *);
Xvoid AddIndex(char *, char *, char *, char *, unsigned long);
Xunsigned long AddTextNode(struct TextNode *, char *, struct TextNode **);
Xvoid FillInIndexData(struct IndexData *, char *, char *, char *, char *, unsigned long);
Xvoid AddNextNode(struct IndexNodeNumbered *, char *, char *, char *, char *, unsigned long);
X
X/* library bases */
Xextern struct ArpBase *ArpBase;
X
X/* here we have some defines */
X#define BUF_SIZE 2000
X#define FORMFEED 12
X#define EOF -1
X
X#define ARP_TEMPLATE "RootDirs/...,VB=VERBOSE/s,NE=NOEXPAND/s"
X#define ARG_DIRS 0
X#define ARG_VERBOSE 1
X#define ARG_NOEXPAND 2
X#define ARG_sizeof 3
X
X#define ESC(a)	  "\x1B[" a "m"
X#define ARGA(a)	  " <" ESC("31") a ESC("32") ">"
X#define ARGB(a)   " [" ESC("33") a ESC("32") "]"
X#define NAME	  ESC("1;33;42") "ADBuildIndex" ESC("0;32;40")
X#define ARP_HELP NAME " v1.0 \xA9 1989 by " \
X		 ESC("4;33;42") "Christopher A. Wichura" ESC("0;33;40") \
X		 " (" ESC("32") "u12401" ESC("33") "@" ESC("32") \
X		 "uicvm.uic.edu" ESC("33") ")\n" ESC("32") \
X		 "Usage:       " NAME ARGA("dir1") ARGA("dir2") ARGA("dir3") \
X		 ARGA("... dirN") "\n                         " \
X		 ARGB("VERBOSE") ARGB("NOEXPAND") \
X		 ESC("31") "\n"
X
X/* this is the main routine */
Xvoid __stdargs __asm main(register __a0 char *cmdline, register __d0 int cmdlen)
X{
X	register signed long c;
X	register char **ptr;
X	char *Args[ARG_sizeof];
X
X	if (!(MainRes = FindTaskResList()))
X		if (!(MainRes = CreateTaskResList())) {
X			Msg("Fatal tracker error!");
X			XCEXIT(10);
X		}
X
X	for (c = 0; c < ARG_sizeof; c++)
X		Args[c] = 0;
X
X	c = GADS(cmdline, cmdlen, ARP_HELP, Args, ARP_TEMPLATE);
X	if (c < 0) {
X		Msg(Args[0]);
X		XCEXIT(5);
X	}
X
X	if (!(MainBuf = ArpAlloc(BUF_SIZE)))
X		NoMem();
X
X	PreParse("*.doc", Pattern);
X
X	DateStamp(&dat.dat_Stamp);
X	dat.dat_Format = FORMAT_DOS;
X	dat.dat_Flags = 0;
X	dat.dat_StrDay = NULL;
X	dat.dat_StrDate = Date;
X	dat.dat_StrTime = Time;
X	StamptoStr(&dat);
X
X	Vflag = (BOOL)Args[ARG_VERBOSE];
X	Eflag = (BOOL)Args[ARG_NOEXPAND];
X
X	ptr = (char **)Args[ARG_DIRS];
X	if (*ptr)
X		while (*ptr)
X			DoFirstDir(*ptr++);
X	else
X		DoFirstDir("AutoDocs:");
X
X	if (Indexs)
X		WriteIndex();
X}
X
X/* this is the top level routine of the scanner.  it's only purpose is
X   to expand a directory name into its full path specification. */
Xvoid DoFirstDir(char *dir)
X{
X	register char *Expanded;
X	BPTR lock;
X	struct DefaultTracker *tracklock;
X
X	if (Eflag) {
X		DoDir(dir);
X		return;
X	}
X
X	if (!(Expanded = ArpAlloc(BUF_SIZE)))
X		NoMem();
X
X	SPrintf(MainBuf, "Error expanding \"%s\" pathname.", dir);
X
X	if (!(lock = ArpLock(dir, ACCESS_READ))) {
X		Puts(MainBuf);
X		return;
X	}
X	tracklock = LastTracker;
X
X	if (!(PathName(lock, Expanded, (BUF_SIZE / DSIZE) - 1))) {
X		Puts(MainBuf);
X		return;
X	}
X	FreeTrackedItem(tracklock);
X
X	DoDir(Expanded);
X
X	FreeTrackedItem((struct DefaultTracker *)Expanded);
X}
X
X/* here we have a high level routine of the scanner.  it takes as its
X   argument a pointer to the directory to scan for doc files.  if it finds
X   any directories in the current directory it will recurse to scan them as
X   well */
Xvoid DoDir(char *dir)
X{
X	register struct FileInfoBlock *fib;
X	register BPTR fhl;
X	register BPTR fh;
X	struct DefaultTracker *track;
X	char *NewPath;
X	char *ErrMsg;
X
X	if (!CreateTaskResList()) {
X		Msg("Fatal tracker error!");
X		XCEXIT(10);
X	}
X
X	if (!(fib = ArpAlloc(sizeof(struct FileInfoBlock))))
X		NoMem();
X
X	if (!(ErrMsg = ArpAlloc(BUF_SIZE)))
X		NoMem();
X
X	SPrintf(ErrMsg, "Error scanning \"%s\" directory.", dir);
X
X	if (!(NewPath = ArpAlloc(BUF_SIZE)))
X		NoMem();
X
X	if (!(fhl = ArpLock(dir, ACCESS_READ))) {
X		Puts(ErrMsg);
X		goto EndDoDir;
X	}
X
X	if (!Examine(fhl, fib)) {
X		Puts(ErrMsg);
X		goto EndDoDir;
X	}
X
X	if (fib->fib_DirEntryType < 0) {
X		Printf("%s is not a directory!\n", dir);
X		goto EndDoDir;
X	}
X
X	if (Vflag)
X		Printf("Scanning directory \"%s\"...\n", dir);
X
X	while (ExNext(fhl, fib)) {
X		ChkAbt();
X
X		strcpy(NewPath, dir);
X		TackOn(NewPath, fib->fib_FileName);
X
X		if (fib->fib_DirEntryType > 0) {
X			DoDir(NewPath);
X			continue;
X		}
X
X		if (!PatternMatch(Pattern, fib->fib_FileName)) {
X			if (Vflag)
X				Printf("\"%s\" is not an AutoDoc file.\n", fib->fib_FileName);
X			continue;
X		}
X
X		if (!(fh = ArpOpen(NewPath, MODE_OLDFILE))) {
X			Printf("Error scanning \"%s\" AutoDoc file.\n", NewPath);
X			continue;
X		}
X
X		track = LastTracker;
X		Printf("Scanning \"%s\"...\n", NewPath);
X		ProcessFile(fh, dir, fib->fib_FileName);
X		FreeTrackedItem(track);
X	}
X
X	if (IoErr() != ERROR_NO_MORE_ENTRIES)
X		Puts(ErrMsg);
X
XEndDoDir:
X	FreeTaskResList();
X}
X
X/* this is the next level down in the scan routines.  it takes a full
X   pathname/filename and scans the file to see what functions it
X   describes as its first argument.  the second arguement points to
X   the path name of this file and the third is a pointer to the actual
X   filename */
Xvoid ProcessFile(BPTR fh, char *path, char *file)
X{
X	register unsigned long offset;
X	register char *ptr1;
X	register char *ptr2;
X	char func[100];
X
X	CurrOffset = 0;
X	for (;;) {
X		ChkAbt();
X
X		GetLine(fh);
X		if (!*MainBuf)
X			return;
X
X		if (*MainBuf == FORMFEED) {
X		   if (*(MainBuf + 1) == FORMFEED)
X			return;
X		   else if (*(MainBuf + 1) == '\n') {
X			GetLine(fh);
X			offset = CurrOffset;
X			if (*MainBuf) {
X				ptr1 = MainBuf;
X				while (*ptr1 == ' ' || *ptr1 == '\t')
X					ptr1++;
X				ptr2 = ptr1;
X				while ((*ptr2 != ' ') && (*ptr2 != '\n') && (*ptr2 != '\t'))
X					ptr2++;
X				*ptr2 = 0;
X				while((*ptr2 != '/') && (ptr2 > ptr1))
X					ptr2--;
X				if (*ptr2 == '/')
X					strcpy(func, ptr2+1);
X				else
X					strcpy(func, ptr2);
X				*ptr2 = 0;
X				AddIndex(func, ptr1, path, file, offset);
X			}
X		   } else
X			Printf("-- Bad function separator found at offset %ld of AutoDoc file.\n", CurrOffset - strlen(MainBuf));
X		}
X	}
X}
X
X/* this is a mighty important routine here.  it adds an entry into the
X   index lists. */
Xvoid AddIndex(char *func, char *lib, char *path, char *file, unsigned long offset)
X{
X	register struct IndexNodeNumbered *innptr = FirstIndex;
X	register struct IndexNodeNumbered *linnptr = NULL;
X	char *splitloc;
X	char *NewPath;
X	register int comparison;
X
X	if (Vflag)
X		Printf("%s; %s; %s; %s; %ld\n", func, lib, path, file, offset);
X
X	if (!(NewPath = ArpAlloc(BUF_SIZE)))
X		NoMem();
X
X	strcpy(NewPath, path);
X	TackOn(NewPath, "a");
X	splitloc = BaseName(NewPath);
X	*splitloc = 0;
X
X	while (innptr) {
X		linnptr = innptr;
X		comparison = Compare(func, innptr->inn_IndexData.id_Func, FirstFunc);
X
X		if (!comparison) {
X			AddNextNode(innptr, func, lib, NewPath, file, offset);
X			goto EndAddIndex;
X		}
X
X		if (comparison > 0)
X			innptr = innptr->inn_Greater;
X		else
X			innptr = innptr->inn_Lesser;
X	}
X
X	/* if we make it here then we need to add a new IndexNodeNumb struct */
X
X	if (!(innptr = (struct IndexNodeNumbered *)RListAlloc(MainRes, sizeof(struct IndexNodeNumbered))))
X		NoMem();
X
X	if (linnptr) {
X		innptr->inn_Parent = linnptr;
X		if (comparison > 0)
X			linnptr->inn_Greater = innptr;
X		else
X			linnptr->inn_Lesser = innptr;
X	} else
X		FirstIndex = innptr;
X
X	innptr->inn_Num = Indexs++;
X	FillInIndexData(&innptr->inn_IndexData, func, lib, NewPath, file, offset);
X
XEndAddIndex:
X	FreeTrackedItem((struct DefaultTracker *)NewPath);
X}
X
X/* this routine will add a NextIndexNode to a chain off a FullIndexNode.
X   it checks to make sure that the node doesn't already exist first
X   as well */
Xvoid AddNextNode(struct IndexNodeNumbered *innptr, char *func, char *lib, char *path, char *file, unsigned long offset)
X{
X	register struct NextIndexNode *ninptr = (struct NextIndexNode *)&innptr->inn_Next;
X	register struct NextIndexNode *lninptr;
X	register int flag;
X
X	while (ninptr) {
X		lninptr = ninptr;
X		flag = 0;
X
X		if (Compare(func, ninptr->nin_IndexData.id_Func, FirstFunc))
X			flag++;
X		if (Compare(lib, ninptr->nin_IndexData.id_Lib, FirstLib))
X			flag++;
X		if (Compare(path, ninptr->nin_IndexData.id_Path, FirstPath))
X			flag++;
X		if (Compare(file, ninptr->nin_IndexData.id_File, FirstFile))
X			flag++;
X		if (offset != ninptr->nin_IndexData.id_Offset)
X			flag++;
X
X		if (flag == 0)
X			return;		/* this node already in list */
X
X		ninptr = ninptr->nin_Next;
X	}
X
X	/* if we get down here we are adding a new node */
X	if (!(ninptr = (struct NextIndexNode *)RListAlloc(MainRes, sizeof(struct NextIndexNode))))
X		NoMem();
X
X	/* we don't need to make sure the last node is there as it always
X	   will not matter what because the first node is guarenteed to be
X	   present (if it wasn't then this routine wouldn't have been
X	   called). */
X	lninptr->nin_Next = ninptr;
X
X	FillInIndexData(&ninptr->nin_IndexData, func, lib, path, file, offset);
X}
X
X/* this routine is used to compare a text string against a value in an
X   IndexData struct.  this is needed because at the time the index is
X   being build we are only stuffing the entry number and not an actual
X   pointer into this location.  Thus we use this routine to look up the
X   actual text based on its number and compare it against that. */
Xint Compare(char *text, char *num, struct TextNode *tn)
X{
X	register int number = 0;
X
X	while (number++ < (int)num)
X		tn = tn->tn_Next;
X
X	return stricmp(text, tn->tn_Text);
X}
X
X/* this routine will write out the index. */
Xvoid WriteIndex(void)
X{
X	if (!(OutHandle = ArpOpen("AutoDocIndex.a", MODE_NEWFILE))) {
X		Msg("Could not create output file.");
X		XCEXIT(5);
X	}
X	Puts("Writing output file...");
X
X	FPrintf(OutHandle, "; AutoDocIndex.a built by ADBuildIndex on %s at %s.\n\n", Date, Time);
X
X	FPrintf(OutHandle, "%s%s at %s%s", LibText1, Date, Time, LibText2);
X
X	FPrintf(OutHandle, "\n; this is the datestamp of the index's creation.\n\n"
X			   "CreationStamp:\n\tdc.l %ld\n\tdc.l %ld\n\tdc.l %ld\n",
X			   dat.dat_Stamp.ds_Days, dat.dat_Stamp.ds_Minute, dat.dat_Stamp.ds_Tick);
X
X	FPrintf(OutHandle, "\n; these are all the index nodes.\n\n");
X	WriteIndexNodes();
X
X	FPrintf(OutHandle, "\n; these are all the function names.\n\n");
X	WriteTextList("Func", FirstFunc);
X
X	FPrintf(OutHandle, "\n; these are all the library names.\n\n");
X	WriteTextList("Lib", FirstLib);
X
X	FPrintf(OutHandle, "\n; these are all the path names.\n\n");
X	WriteTextList("Path", FirstPath);
X
X	FPrintf(OutHandle, "\n; these are all the file names.\n\n");
X	WriteTextList("File", FirstFile);
X
X	FPrintf(OutHandle, "%s", LibText3);
X}
X
X/* this routine will spit out all the index nodes */
Xvoid WriteIndexNodes(void)
X{
X	register int Nexts = 0;
X
X	Printf("  Writing index nodes...");
X
X	FPrintf(OutHandle, "FirstIndexNode:\n");
X	if (FirstIndex->inn_Greater)
X		FPrintf(OutHandle, "\tdc.l Index%ld\n", FirstIndex->inn_Greater->inn_Num);
X	else
X		FPrintf(OutHandle, "\tdc.l 0\n");
X	if (FirstIndex->inn_Lesser)
X		FPrintf(OutHandle, "\tdc.l Index%ld\n", FirstIndex->inn_Lesser->inn_Num);
X	else
X		FPrintf(OutHandle, "\tdc.l 0\n");
X	if (FirstIndex->inn_Next)
X		FPrintf(OutHandle, "\tdc.l Next0_0\n");
X	else
X		FPrintf(OutHandle, "\tdc.l 0\n");
X	FPrintf(OutHandle, "\tdc.l Func%ld\n", (int)FirstIndex->inn_IndexData.id_Func);
X	FPrintf(OutHandle, "\tdc.l Lib%ld\n",  (int)FirstIndex->inn_IndexData.id_Lib );
X	FPrintf(OutHandle, "\tdc.l Path%ld\n", (int)FirstIndex->inn_IndexData.id_Path);
X	FPrintf(OutHandle, "\tdc.l File%ld\n", (int)FirstIndex->inn_IndexData.id_File);
X	FPrintf(OutHandle, "\tdc.l %ld\n", FirstIndex->inn_IndexData.id_Offset);
X	Nexts += WriteNextNodes(FirstIndex);
X
X	Nexts += WriteIndexTree(FirstIndex);
X
X	Printf("  %ld nodes with %ld sub-nodes output.\n", Indexs, Nexts);
X}
X
X/* this writes out the bulk of the index tree */
Xint WriteIndexTree(struct IndexNodeNumbered *innptr)
X{
X	register struct IndexNodeNumbered *dinnptr;
X	register int nexts = 0;
X
X	for (;innptr;) {
X		ChkAbt();
X
X		if (innptr->inn_Greater && innptr->inn_Greater->inn_Parent) {
X			innptr = innptr->inn_Greater;
X			continue;
X		}
X
X		if (innptr->inn_Lesser && innptr->inn_Lesser->inn_Parent) {
X			innptr = innptr->inn_Lesser;
X			continue;
X		}
X
X		if (innptr->inn_Num) {
X			FPrintf(OutHandle, "\nIndex%ld:\n", innptr->inn_Num);
X			if (innptr->inn_Greater)
X				FPrintf(OutHandle, "\tdc.l Index%ld\n", innptr->inn_Greater->inn_Num);
X			else
X				FPrintf(OutHandle, "\tdc.l 0\n");
X			if (innptr->inn_Lesser)
X				FPrintf(OutHandle, "\tdc.l Index%ld\n", innptr->inn_Lesser->inn_Num);
X			else
X				FPrintf(OutHandle, "\tdc.l 0\n");
X			if (innptr->inn_Next)
X				FPrintf(OutHandle, "\tdc.l Next%ld_0\n", innptr->inn_Num);
X			else
X				FPrintf(OutHandle, "\tdc.l 0\n");
X			FPrintf(OutHandle, "\tdc.l Func%ld\n", (int)innptr->inn_IndexData.id_Func);
X			FPrintf(OutHandle, "\tdc.l Lib%ld\n",  (int)innptr->inn_IndexData.id_Lib );
X			FPrintf(OutHandle, "\tdc.l Path%ld\n", (int)innptr->inn_IndexData.id_Path);
X			FPrintf(OutHandle, "\tdc.l File%ld\n", (int)innptr->inn_IndexData.id_File);
X			FPrintf(OutHandle, "\tdc.l %ld\n", innptr->inn_IndexData.id_Offset);
X			nexts += WriteNextNodes(innptr);
X		}
X
X		dinnptr = innptr;
X		innptr = innptr->inn_Parent;
X		dinnptr->inn_Parent = NULL;
X	}
X
X	return nexts;
X}
X
X/* this will spit out all the NextIndexNodes that might be attached to a
X   FullIndex */
Xint WriteNextNodes(struct IndexNodeNumbered *innptr)
X{
X	register struct NextIndexNode *ninptr = innptr->inn_Next;
X	register int nexts = 0;
X
X	while (ninptr) {
X		ChkAbt();
X
X		FPrintf(OutHandle, "\nNext%ld_%ld:\n", innptr->inn_Num, nexts);
X		if (ninptr->nin_Next)
X			FPrintf(OutHandle, "\tdc.l Next%ld_%ld\n", innptr->inn_Num, nexts + 1);
X		else
X			FPrintf(OutHandle, "\tdc.l 0\n");
X		FPrintf(OutHandle, "\tdc.l Func%ld\n", (int)ninptr->nin_IndexData.id_Func);
X		FPrintf(OutHandle, "\tdc.l Lib%ld\n",  (int)ninptr->nin_IndexData.id_Lib );
X		FPrintf(OutHandle, "\tdc.l Path%ld\n", (int)ninptr->nin_IndexData.id_Path);
X		FPrintf(OutHandle, "\tdc.l File%ld\n", (int)ninptr->nin_IndexData.id_File);
X		FPrintf(OutHandle, "\tdc.l %ld\n", ninptr->nin_IndexData.id_Offset);
X
X		ninptr = ninptr->nin_Next;
X		nexts++;
X	}
X
X	return nexts;
X}
X
X/* this routine will spit a TextNode list out to the output file */
Xvoid WriteTextList(char *name, struct TextNode *tn)
X{
X	register int number = 0;
X
X	Printf("  Writing %ss...", name);
X
X	while (tn) {
X		ChkAbt();
X
X		FPrintf(OutHandle, "%s%ld: dc.b \"%s\",0\n", name, number, tn->tn_Text);
X		number++;
X		tn = tn->tn_Next;
X	}
X
X	Printf("  %ld unique entries output.\n", number);
X}
X
X/* this routine will store all the fields needed into an IndexData struct */
Xvoid FillInIndexData(struct IndexData *idptr, char *func, char *lib, char *path, char *file, unsigned long offset)
X{
X	idptr->id_Func = (char *)AddTextNode(FirstFunc, func, &FirstFunc);
X	idptr->id_Lib  = (char *)AddTextNode(FirstLib,  lib,  &FirstLib );
X	idptr->id_Path = (char *)AddTextNode(FirstPath, path, &FirstPath);
X	idptr->id_File = (char *)AddTextNode(FirstFile, file, &FirstFile);
X	idptr->id_Offset = offset;
X}
X
X/* this routine will add a text node to the appropriate list.  it checks
X   to make sure that the entry does not exist and will not add it if it
X   does. */
Xunsigned long AddTextNode(struct TextNode *tn, char *entry, struct TextNode **first)
X{
X	register struct TextNode *ltn = NULL;
X	register unsigned long number = 0;
X
X	while (tn) {
X		if (!stricmp(tn->tn_Text, entry))
X			return number;
X
X		ltn = tn;
X		tn = tn->tn_Next;
X		number++;
X	}
X
X	if (!(tn = (struct TextNode *)RListAlloc(MainRes, strlen(entry) + 5)))
X		NoMem();
X
X	strcpy(tn->tn_Text, entry);
X	if (ltn)
X		ltn->tn_Next = tn;
X	else
X		*first = tn;
X
X	return number;
X}
X
X/* this routine prints out general error messages */
Xvoid Msg(char *msg)
X{
X	Printf("- ADBuildIndex: %s\n", msg);
X}
X
X/* the most common error message that causes us to exit is an out of
X   memory message so here we have it as a seperate function */
Xvoid NoMem(void)
X{
X	Msg("Out of memory!");
X	XCEXIT(5);
X}
X
X/* this routine will get a line from the specified input file */
Xvoid GetLine(BPTR fh)
X{
X	register char *ptr = MainBuf;
X	register int c;
X	register int count = 0;
X
X	while ((c = GetChar(fh)) != EOF) {
X		*ptr++ = c;
X		count++;
X		if (count == BUF_SIZE - 1 || c == '\n')
X			break;
X	}
X
X	*ptr = 0;
X}
X
X/* this is the buffered input routine.  note that it checks the given file
X   handle against the last used file handle to know if it has been given a
X   new file and must do a new seek. */
Xint GetChar(BPTR fh)
X{
X	register int c;
X	static int bufptr = 0;
X	static char buf[81];
X
X	if (CurrOffset == 0 || bufptr == 80) {
X		c = Read(fh, buf, 80);
X		if (c == 0)
X			return EOF;
X		if (c == -1) {
X			Printf("-- DOS Error #%ld reading AutoDoc file.", IoErr());
X			return EOF;
X		}
X		buf[c] = EOF;
X		bufptr = 0;
X	}
X
X	CurrOffset++;
X
X	/* this will make sure we always return EOF if we hit the end */
X	c = (int)buf[bufptr++];
X	if (c == EOF)
X		bufptr = 80;
X
X	return c;
X}
X
X/* this function will check for an abort and exit gracefully if so.  Note
X   that many of the resources we use are tracked by arp.library and thus
X   need not be explicitly freed here. */
Xvoid ChkAbt(void)
X{
X	if (CheckAbort(NULL)) {
X		Msg("Execution terminated!");
X		XCEXIT(1);
X	}
X}
END_OF_FILE
if test 20082 -ne `wc -c <'ADBuildIndex.c'`; then
    echo shar: \"'ADBuildIndex.c'\" unpacked with wrong size!
fi
# end of 'ADBuildIndex.c'
fi
if test -f 'ADLUstartup.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ADLUstartup.a'\"
else
echo shar: Extracting \"'ADLUstartup.a'\" \(2507 characters\)
sed "s/^X//" >'ADLUstartup.a' <<'END_OF_FILE'
X INCLUDE "libraries/ArpBase.i"
X INCLUDE "exec/execbase.i"
X INCLUDE "libraries/dosextens.i"
X
X XREF _main
X XREF _DOSBase
X
X XREF _LVOOpenLibrary
X XREF _LVOCloseLibrary
X XREF _LVOSetSignal
X XREF _LVOForbid
X XREF _LVOWaitPort
X XREF _LVOGetMsg
X XREF _LVOReplyMsg
X
X XREF _LinkerDB
X XREF __BSSBAS
X XREF __BSSLEN
X XREF _RESLEN
X XREF _RESBASE
X XREF _NEWDATAL
X
XCALL	MACRO
X	jsr _LVO\1(a6)
X	ENDM
X
X  SECTION StartCode,CODE
X
X; arp resident tag goes here
X	RESIDENT 2048 	
X
Xinit:
X	movem.l	d0/a0,-(sp)
X	lea	_LinkerDB,a4
X	movea.l	4,a6
X	lea	ARPlib(pc),a1
X	moveq	#39,d0
X	CALL	OpenLibrary
X	tst.l	d0
X	bne.s	__main
X
X	lea	DOSlib(pc),a1
X	CALL	OpenLibrary
X	tst.l	d0
X	beq.s	bomb
X
X	move.l	d0,a6
X	CALL	Output
X	move.l	d0,d1
X	beq.s	bomb
X
X	lea	Msg1(pc),a0
X	move.l	a0,d2
X	moveq	#Msg1Len,d3
X	CALL	Write
X
X	move.l	a6,a1
X	movea.l	4,a6
X	CALL	CloseLibrary
X	moveq	#0,d0
X
Xbomb:
X	addq.l	#8,sp
X	rts
X
XDOSlib	dc.b "dos.library",0
X
XMsg1	dc.b "You need "
XARPlib	dc.b "arp.library",0
X	dc.b " V39+",10,0
XMsg1Len	EQU *-Msg1
X	ds.w 0
X
X__main:
X	move.l	d0,a6
X	sub.l	#_RESBASE,a4
X
X; get mem to hold data and bss stuff
X	move.l	#_RESLEN,d0
X	CALL	ArpAlloc
X	tst.l	d0
X	bne.s	gotmem
X
X	moveq	#20,d0
X	moveq	#0,d2
X	CALL	ArpExit
X
X; get ready to copy data over into freshly alloced data area
Xgotmem:	move.l	d0,a0
X	move.l	d0,a2
X
X	move.l	d0,a1
X	move.l	#_NEWDATAL,d0
Xcpy:	move.l	(a4)+,(a0)+
X	subq.l	#1,d0
X	bne.s	cpy
X
X; now do the relocs for resident data
X	move.l	(a4)+,d0
Xreloc:	beq.s	nreloc
X	move.l	a1,a0
X	add.l	(a4)+,a0
X	add.l	(a0),a2
X	move.l	a2,(a0)
X	move.l	a1,a2
X	subq.l	#1,d0
X	bra.s	reloc
X
Xnreloc:	move.l	a1,a4
X	add.l	#_RESBASE,a4
X
X; stash some important junk away
X	move.l	a6,_ArpBase(a4)
X	move.l	DosBase(a6),_DOSBase(a4)
X	movea.l	4,a6
X	move.l	a6,_SysBase(a4)
X	movem.l	sp,__StackPtr(a4)
X
X; get address of our task
X	move.l	ThisTask(a6),a3
X
X; clear any pending signals
X	moveq	#0,d0
X	move.l	#$00003000,d1
X	CALL	SetSignal
X
X; check for workbench and exit fast if so
X	tst.l	pr_CLI(a3)
X	bne.s	FromCLI
X
X	lea	pr_MsgPort(a3),a0
X	CALL	WaitPort
X	lea	pr_MsgPort(a3),a0
X	CALL	GetMsg
X	move.l	d0,d2
X	beq.s	ExitToDOS
X
X	CALL	Forbid
X	movea.l	d2,a1
X	CALL	ReplyMsg
X	moveq	#0,d0
X	bra.s	ExitToDOS
X
XFromCLI:
X	movem.l	(sp)+,d0/a0
X	jsr	_main
X	moveq.l	#0,d0
X	bra.s	ExitToDOS
X
X XDEF _XCEXIT
X_XCEXIT:
X	move.l	4(sp),d0
X XDEF @XCEXIT
X@XCEXIT:
X
XExitToDOS:
X	move.l	_ArpBase(a4),a6
X	movea.l	__StackPtr(a4),sp
X	moveq	#0,d2
X	CALL	ArpExit
X
X; ---- This is a data section
X
X   SECTION __MERGED,BSS
X
X XDEF _ArpBase
X XDEF _SysBase
X XDEF __StackPtr
X
X_ArpBase    ds.b 4
X_SysBase    ds.b 4
X__StackPtr  ds.b 4
X
X   END
END_OF_FILE
if test 2507 -ne `wc -c <'ADLUstartup.a'`; then
    echo shar: \"'ADLUstartup.a'\" unpacked with wrong size!
fi
# end of 'ADLUstartup.a'
fi
if test -f 'ADLookUp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ADLookUp.c'\"
else
echo shar: Extracting \"'ADLookUp.c'\" \(6868 characters\)
sed "s/^X//" >'ADLookUp.c' <<'END_OF_FILE'
X/*	ADLookUp.c
X	(c) 1989 by Christopher A. Wichura  (u12401@uicvm.uic.edu)
X
X	Created:  12/17/89
X
X	Compile with:  LC -d2 -v -rr -cs ADLookUp
X*/
X
X#include <exec/types.h>
X#include <libraries/ArpBase.h>
X#include <proto/dos.h>
X
X/* here we define the IndexData structure so we know what's what */
Xstruct IndexData {
X	char *id_Func;
X	char *id_Lib;
X	char *id_Path;
X	char *id_File;
X	unsigned long id_Offset;
X};
X
X/* here we prototype the four functions found in the index library */
Xstruct IndexData *GetFirstIndex(char *);
Xstruct IndexData *GetNextIndex(struct IndexData *);
Xvoid FreeIndex(struct IndexData *);
Xvoid GetCreationStamp(struct DateStamp *);
X#pragma libcall AutoDocIndexBase GetFirstIndex    1e 801
X#pragma libcall AutoDocIndexBase GetNextIndex     24 801
X#pragma libcall AutoDocIndexBase FreeIndex        2a 801
X#pragma libcall AutoDocIndexBase GetCreationStamp 30 101
X
X/* here we prototype the functions found/used in this file */
Xvoid Msg(char *);
Xint  GetChar(void);
Xvoid GetLine(void);
Xvoid PrintFunc(char *);
Xint  ChkAbt(struct IndexData *, BOOL);
Xvoid DisplayFunc(struct IndexData *);
Xvoid __builtin_strcpy(char *, char *);
Xvoid XCEXIT(int);
X
X/* handle the library bases */
Xstruct Library *AutoDocIndexBase;
Xextern struct ArpBase *ArpBase;
X
X/* here we have some general defines */
X#define BUF_SIZE 2000
X#define FORMFEED 12
X#define EOF -1
X
X#define ARP_TEMPLATE "Functions/...,TO/k,OPT/k"
X#define ARG_FILES 0
X#define ARG_TO 1
X#define ARG_OPT 2
X#define ARG_sizeof 3
X
X#define ESC(a)	  "\x1B[" a "m"
X#define ARGA(a)	  " <" ESC("31") a ESC("32") ">"
X#define ARGB(a,b) " [" ESC("33") a ESC("31") " " b ESC("32") "]"
X#define NAME	  ESC("1;33;42") "ADLookUp" ESC("0;32;40")
X#define ARP_HELP NAME " v1.0 \xA9 1989 by " \
X		 ESC("4;33;42") "Christopher A. Wichura" ESC("0;33;40") \
X		 " (" ESC("32") "u12401" ESC("33") "@" ESC("32") \
X		 "uicvm.uic.edu" ESC("33") ")\n" ESC("32") \
X		 "Usage:   " NAME ARGA("func1") ARGA("func2") ARGA("func3") \
X		 ARGA("... funcN") ARGB("TO", "Outfile") ARGB("OPT", "B|C") \
X		 ESC("31") "\n"
X
X/* make the file handles global so all functions can use them */
XBPTR OutHandle;
XBPTR InHandle;
X
X/* the pointers to our storage buffers will also be made global */
Xchar *MainBuf;
Xchar *FileErrBuf;
X
X/* here we have a couple of global flags */
XBOOL NewSeek;
XBOOL Banners = 0;
XBOOL SayCreation = 0;
X
X/* here we have the main routine */
Xvoid __stdargs __asm main (register __a0 char *cmdline, register __d0 int cmdlen)
X{
X	register signed long c;
X	register char *optp;
X	register char **ptr;
X	register BPTR fh;
X	char *Args[ARG_sizeof];
X
X	OutHandle = Output();
X
X	if (!(AutoDocIndexBase = ArpOpenLibrary("AutoDocIndex.library", 0))) {
X		Msg("No index library available!");
X		XCEXIT(10);
X	}
X
X	for (c = 0; c < ARG_sizeof; c++)
X		Args[c] = 0;
X
X	c = GADS(cmdline, cmdlen, ARP_HELP, Args, ARP_TEMPLATE);
X	if (c < 0) {
X		Msg(Args[0]);
X		XCEXIT(5);
X	}
X
X	if (Args[ARG_OPT]) {
X		optp = Args[ARG_OPT];
X
X		while ((c = Toupper(*optp++))) {
X			switch (c) {
X				case 'B':
X				Banners = 1;
X				break;
X
X				case 'C':
X				SayCreation = 1;
X				break;
X			}
X		}
X	}
X
X	if (Args[ARG_TO]) {
X		if (!(fh = ArpOpen(Args[ARG_TO], MODE_NEWFILE))) {
X			Msg("Could not create output file!");
X			XCEXIT(5);
X		}
X		OutHandle = fh;
X	}
X
X	if (!(MainBuf = ArpAlloc(BUF_SIZE))) {
X		Msg("Out of memory!");
X		XCEXIT(5);
X	}
X
X	if (SayCreation) {
X		struct DateTime dat;
X		char Date[LEN_DATSTRING];
X		char Time[LEN_DATSTRING];
X
X		GetCreationStamp(&dat.dat_Stamp);
X		dat.dat_Format = FORMAT_DOS;
X		dat.dat_Flags = 0;
X		dat.dat_StrDay = NULL;
X		dat.dat_StrDate = Date;
X		dat.dat_StrTime = Time;
X
X		for (c = 0; c < LEN_DATSTRING; c++)
X			Date[c] = Time[c] = 0;
X
X		StamptoStr(&dat);
X
X		SPrintf(MainBuf, "Index created on %s at %s.", Date, Time);
X		Msg(MainBuf);
X		XCEXIT(0);
X	}
X
X	if (!(FileErrBuf = ArpAlloc(BUF_SIZE))) {
X		Msg("Out of memory!");
X		XCEXIT(5);
X	}
X
X	ptr = (char **)Args[ARG_FILES];
X	while (*ptr)
X		PrintFunc(*ptr++);
X}
X
X/* this is our general message output routine. */
Xvoid Msg(char *msg)
X{
X	FPrintf(OutHandle, "- ADLookUp: %s\n", msg);
X}
X
X/* this is the routine that looks up a function and its duplicates */
Xvoid PrintFunc(char *function)
X{
X	register struct IndexData *idptr;
X	register struct IndexData *lidptr;
X
X	if (!(idptr = GetFirstIndex(function))) {
X		SPrintf(FileErrBuf, "\"%s\" not found.", function);
X		Msg(FileErrBuf);
X		return;
X	}
X
X	while (idptr) {
X		ChkAbt(idptr, 0);
X		DisplayFunc(idptr);
X		lidptr = idptr;
X		idptr = GetNextIndex(idptr);
X		FreeIndex(lidptr);
X	}
X}
X
X/* this routine actually sends the function to the OutHandle */
Xvoid DisplayFunc(struct IndexData *idptr)
X{
X	register struct DefaultTracker *track;
X
X	__builtin_strcpy(MainBuf, idptr->id_Path);
X	TackOn(MainBuf, idptr->id_File);
X	SPrintf(FileErrBuf, "Error reading \"%s\" AutoDoc file.", MainBuf);
X
X	if (!(InHandle = ArpOpen(MainBuf, MODE_OLDFILE))) {
X		Msg(FileErrBuf);
X		return;
X	}
X	track = LastTracker;
X
X	if (Seek(InHandle, idptr->id_Offset, OFFSET_BEGINNING) == -1) {
X		Msg(FileErrBuf);
X		goto EndDisplay;
X	}
X
X	NewSeek = 1;
X
X	if (Banners)
X		FPrintf(OutHandle, "*** AutoDoc: %s in %s ***\n",
X			idptr->id_Func, idptr->id_Lib);
X
X	for (;;) {
X		if (ChkAbt(idptr, 1)) {
X			Msg("Read aborted.");
X			break;
X		}
X
X		GetLine();
X		if (*MainBuf == 0 || *MainBuf == FORMFEED)
X			break;
X		FPrintf(OutHandle, "%s", MainBuf);
X	}
X
XEndDisplay:
X	FreeTrackedItem(track);
X}
X
X/* this function will input one lines worth from the given file handle */
Xvoid GetLine(void)
X{
X	register char *ptr = MainBuf;
X	register int c;
X	register int count = 0;
X
X	while ((c = GetChar()) != EOF) {
X		*ptr++ = c;
X		count++;
X		if (count == BUF_SIZE - 1 || c == '\n')
X			break;
X	}
X
X	*ptr = 0;
X}
X
X/* here we do buffered input for getting a character at a time */
Xint GetChar(void)
X{
X	static int bufptr = 0;
X	static char buf[81];
X
X	if (NewSeek || (bufptr == 80)) {
X		bufptr = Read(InHandle, buf, 80);
X		if (bufptr == 0)
X			return EOF;
X		if (bufptr == -1) {
X			Msg(FileErrBuf);
X			return EOF;
X		}
X		buf[bufptr] = EOF;
X		bufptr = NewSeek = 0;
X	}
X
X	return (int)buf[bufptr++];
X}
X
X/* this routine will check if the user hit abort and print a message and
X   die if so.  Virtually all resources used by ADLookUp are being tracked
X   by arp.library for us so we don't have to worry about freeing them all.
X   However, we do need to make sure that we free the current index node (if
X   it exists) so that is passed to this routine as its only argument.
X   if the second argument is 0 then it will abort regardless of which
X   abort key you hit.  if the second arg is 1 it will abort on
X   CTRL-C, but return a break flag if it gets CTRL-D */
X#define MASK SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D
Xint ChkAbt(struct IndexData *idptr, BOOL flag)
X{
X	register BOOL masks;
X
X	if ((masks = CheckBreak(MASK, NULL))) {
X		if (flag && (masks & SIGBREAKF_CTRL_D))
X			return 1;
X		Msg("Execution terminated!");
X		if (idptr)
X			FreeIndex(idptr);
X		XCEXIT(1);
X	}
X
X	return 0;
X}
END_OF_FILE
if test 6868 -ne `wc -c <'ADLookUp.c'`; then
    echo shar: \"'ADLookUp.c'\" unpacked with wrong size!
fi
# end of 'ADLookUp.c'
fi
if test -f 'LibText1.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'LibText1.txt'\"
else
echo shar: Extracting \"'LibText1.txt'\" \(1509 characters\)
sed "s/^X//" >'LibText1.txt' <<'END_OF_FILE'
X	SECTION AutoDocLib,CODE
X
X NOLIST
X INCLUDE "exec/types.i"
X INCLUDE "exec/libraries.i"
X INCLUDE "exec/lists.i"
X INCLUDE "exec/alerts.i"
X INCLUDE "exec/initializers.i"
X INCLUDE "exec/resident.i"
X INCLUDE "exec/memory.i"
X INCLUDE "libraries/dos.i"
X LIST
X
X;---- XREF all the exec routines we need
X XREF _LVOFreeMem
X XREF _LVORemove
X
X; here we define the library's base structure
X	STRUCTURE Base,LIB_SIZE
X	UBYTE base_Flags
X	UBYTE base_pad
X	; now properly aligned
X	ULONG base_SysLib
X	ULONG base_SegList
X	LABEL base_SIZEOF
X
X; the first executable location sets an error and returns in case someone
X; tries to load the library as a load moudle instead of OpenLibrary()ing it
X	moveq.l #-1,d0
X	rts
X
X; the romtag structure for this library
XinitDDescrip:
X		;STRUCTURE RT,0
X	dc.w RTC_MATCHWORD	; UWORD RT_MATCHWORD
X	dc.l initDDescrip	; APTR  RT_MATCHTAG
X	dc.l EndCode		; APTR  RT_ENDSKIP
X	dc.b RTF_AUTOINIT	; UBYTE RT_FLAGS
X	dc.b VERSION		; UBYTE RT_VERSION
X	dc.b NT_LIBRARY		; UBYTE RT_TYPE
X	dc.b 0			; BYTE  RT_PRI
X	dc.l AutoDocName	; APTR  RT_NAME
X	dc.l idString		; APTR  RT_IDSTRING
X	dc.l Init		; APTR  RT_INIT
X
X; the name of the library
XAutoDocName: dc.b "AutoDocIndex.library",0
X
X; major version number
XVERSION: EQU 1
X
X; particular revision number
XREVISION: EQU 0
X
X; text identifier tag for the library
X	ds.w 0	; word align this as some prgs (XOper) want it so...
XidString: dc.b 'AutoDocIndex.library v1.0 (18 Dec 1989), ',$a9,' 1989 '
X          dc.b 'by Christopher A. Wichura',13,10
X          dc.b 'Index built on 
END_OF_FILE
if test 1509 -ne `wc -c <'LibText1.txt'`; then
    echo shar: \"'LibText1.txt'\" unpacked with wrong size!
fi
# end of 'LibText1.txt'
fi
if test -f 'LibText2.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'LibText2.txt'\"
else
echo shar: Extracting \"'LibText2.txt'\" \(5554 characters\)
sed "s/^X//" >'LibText2.txt' <<'END_OF_FILE'
X',13,10,0
X
X; word align everything
X	ds.w 0
X
X; this is the init structure that out RTF_AUTOINIT told exec to look for
XInit:
X	dc.l base_SIZEOF	; size of library base data space
X	dc.l funcTable		; pointer to the function initializers
X	dc.l dataTable		; pointer to the data initializers
X	dc.l initRoutine	; routine to run
X
X; here we have the function table.  it, of course, starts with the standard
X; library routines like Open, etc.
XfuncTable:
X	dc.l Open
X	dc.l Close
X	dc.l Expunge
X	dc.l Null		; reserved routine
X
X; my library routines
X	dc.l GetFirstIndex
X	dc.l GetNextIndex
X	dc.l FreeIndex
X	dc.l GetCreationStamp
X
X; end of library function list
X	dc.l -1
X
X; static data structures initilization table
XdataTable:
X	INITBYTE LN_TYPE,NT_LIBRARY
X	INITLONG LN_NAME,AutoDocName
X	INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
X	INITWORD LIB_VERSION,VERSION
X	INITWORD LIB_REVISION,REVISION
X	INITLONG LIB_IDSTRING,idString
X	dc.l 0
X
X; after the library has been allocated this next routine gets called.
X; d0 = library's pointer, a0 = segment list
X;
X; returning non-zero means ok to link library into system list
XinitRoutine:
X	move.l	a5,-(sp)
X	move.l	d0,a5		; make library base easy to get at
X
X	move.l	a6,base_SysLib(a5)	; save pointer to exec
X	move.l	a0,base_SegList(a5)	; save pointer to loaded code
X
X	move.l	(sp)+,a5
X	rts
X
X; here we have the library interface Open routine.  returns library
X; pointer or null if it fails (which it never will)
XOpen:
X	addq.w	#1,LIB_OPENCNT(a6)		; say another opened us
X	bclr	#LIBB_DELEXP,base_Flags(a6)	; prevent delayed expunges
X
X	move.l	a6,d0
X	rts
X
X; this is the library interface Close routine.  returns seglist if no
X; more opencnt and delayed expunge waiting, otherwise return null.
XClose:
X	moveq	#0,d0
X	subq.w	#1,LIB_OPENCNT(A6)		; one less open now
X	bne	1$				; still got someone around
X
X	btst	#LIBB_DELEXP,base_Flags(a6)	; is delayed expunge pending?
X	beq.s	1$
X
X	bsr	Expunge				; yes, so do it
X1$:
X	rts
X
X; this is the library interface Expunge routine.
XExpunge:
X	movem.l	d2/a5/a6,-(sp)
X	move.l	a6,a5
X	move.l	base_SysLib(a5),a6		; get exec pointer
X
X	tst.w	LIB_OPENCNT(a5)			; anyone have us open?
X	beq.s	1$
X
X	bset	#LIBB_DELEXP,base_Flags(a5)	; still open so set delayed exp
X	moveq	#0,d0
X	bra.s	Expunge_End
X
X1$:	; no one left so dump this sucker!
X	move.l	base_SegList(a5),d2
X
X	move.l	a5,a1
X	jsr	_LVORemove(a6)	; unlink from library list
X
X	moveq	#0,d0
X	move.l	a5,a1
X	move.w	LIB_NEGSIZE(a5),d0
X
X	sub.l	d0,a1
X	add.w	LIB_POSSIZE(a5),d0
X
X	jsr	_LVOFreeMem(a6)	; free the mem used by cawlib itself
X
X	move.l	d2,d0	; put seglist as return value for success
X
XExpunge_End:
X	movem.l	(sp)+,d2/a5/a6
X	rts
X
XNull:
X	moveq	#0,d0	; reserved for future expansion I guess.
X	rts		; MUST ALWAYS RETURN NULL FOR FUTURE COMPATIBILITY!
X
X; --------------------------------------------------------------------------
X; here we have the first library routine.  this one looks for an occurance
X; of a function name in the index list.  it takes a pointer to the needed
X; function name as its only argument in register a0.
X
XGetFirstIndex:
X	movem.l	a2-a3,-(sp)
X	movea.l	a0,a3			; save pointer to function name
X	lea	FirstIndexNode(pc),a2	; get pointer to first index node
X
X1$	move.l	a2,d0			; test if no more nodes
X	beq.s	4$			; yes so exit with zero in d0
X
X	movea.l	a3,a0
X	movea.l	12(a2),a1
X	bsr	StrCmp			; compare function against index
X
X	tst.l	d0			; check if equal
X	bne.s	2$
X
X	lea	12(a2),a0		; yes so return index data node
X	move.l	a0,d0
X	bra.s	4$
X
X2$	tst.l	d0
X	ble.s	3$
X
X	movea.l	(a2),a2			; lexically greater so go up
X	bra.s	1$
X
X3$	movea.l	4(a2),a2		; lexically lesser so go down
X	bra.s	1$
X
X4$	movem.l	(sp)+,a2-a3		; all done so clean up stack and
X	rts				; go home
X
X; --------------------------------------------------------------------------
X; this function will return the next node matching a function name.  it
X; takes a pointer to an IndexData as its only argument in register a0.
X
XGetNextIndex:
X	suba.l	#4,a0
X	movea.l	(a0),a1
X	move.l	a1,d0
X	bne.s	1$
X
X	rts			; no more nodes so return zero
X
X1$	lea	4(a1),a0	; got another node so return its indexdata
X	move.l	a0,d0
X	rts
X
X; --------------------------------------------------------------------------
X; this routine does nothing in this version of the library.  it is provided
X; for future expansion.  It takes as its argument a pointer in a0 to an
X; IndexData structure returned by GetFirstIndex/GetNextIndex
X
XFreeIndex:
X	moveq	#0,d0
X	rts
X
X; --------------------------------------------------------------------------
X; this routine will return a date stamp that holds the index's creation date
X; and time.  it takes as its only arguement a vector to three long words to
X; place the stamp in, much like the AmigaDOS DateStamp() function returns
X; the current system time.
XGetCreationStamp:
X	lea	CreationStamp(pc),a0
X	movea.l	d1,a1
X	moveq	#2,d0
X1$	move.l	(a0)+,(a1)+
X	dbf	d0,1$
X	rts
X
X; --------------------------------------------------------------------------
X; here we have the string compare function used by GetFirstIndex.  it takes
X; pointers to the two strings to be compared in registers a0 and a1.
X
XStrCmp:
X	moveq	#0,d0
X	moveq	#0,d1
X
X1$	move.b	(a0)+,d0
X	move.b	(a1)+,d1
X
X	cmpi.b	#'a',d0			; check if d0 needs case change
X	blt.s	2$
X	cmpi.b	#'z',d0
X	bgt.s	2$
X	subi.b	#'a'-'A',d0
X
X2$	cmpi.b	#'a',d1			; check if d1 needs case change
X	blt.s	3$
X	cmpi.b	#'z',d1
X	bgt.s	3$
X	subi.b	#'a'-'A',d1
X
X3$	sub.l	d1,d0			; do a compare
X	bne.s	4$
X	tst.b	d1			; check if more to do
X	bne.s	1$
X
X4$	rts
X
X; --------------------------------------------------------------------------
X; here we have the actual index data tree
END_OF_FILE
if test 5554 -ne `wc -c <'LibText2.txt'`; then
    echo shar: \"'LibText2.txt'\" unpacked with wrong size!
fi
# end of 'LibText2.txt'
fi
if test -f 'LibText3.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'LibText3.txt'\"
else
echo shar: Extracting \"'LibText3.txt'\" \(55 characters\)
sed "s/^X//" >'LibText3.txt' <<'END_OF_FILE'
X
X	ds.w 0
X
XEndCode:	; marker for end of this stuff
X	END
END_OF_FILE
if test 55 -ne `wc -c <'LibText3.txt'`; then
    echo shar: \"'LibText3.txt'\" unpacked with wrong size!
fi
# end of 'LibText3.txt'
fi
if test -f 'lmkfile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lmkfile'\"
else
echo shar: Extracting \"'lmkfile'\" \(646 characters\)
sed "s/^X//" >'lmkfile' <<'END_OF_FILE'
X# this is a make file for ADLookUp and its supporting programs.
X# created 12/21/89 by Christopher A. Wichura
X
XDEBUG = -d2
XFLAGS = $(DEBUG) -v -cs -rr
XLIBS = LIB:ARP.lib LIB:LCR.lib LIB:amiga.lib
X
XND = NODEBUG
XLFLAGS = $(ND) SMALLCODE SMALLDATA
X
X.c.o:
X	LC $(FLAGS) $*
X
X.a.o:
X	ASM -iINCLUDE: $*
X
X.txt.o:
X	TXTtoOBJ $*.txt $*.o _$* CODE
X
XALL: ADLookUp ADBuildIndex
X
XADLookUp: ADLUstartup.o ADLookUp.o
X	blink ADLUstartup.o ADLookUp.o to ADLookUp LIB $(LIBS) $(LFLAGS)
X
XADBuildIndex: ADBIstartup.o ADBuildIndex.o LibText1.o LibText2.o LibText3.o
X	blink ADBIstartup.o ADBuildIndex.o LibText1.o LibText2.o LibText3.o to ADBuildIndex LIB $(LIBS) $(LFLAGS)
END_OF_FILE
if test 646 -ne `wc -c <'lmkfile'`; then
    echo shar: \"'lmkfile'\" unpacked with wrong size!
fi
# end of 'lmkfile'
fi
if test -f 'readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'readme'\"
else
echo shar: Extracting \"'readme'\" \(8325 characters\)
sed "s/^X//" >'readme' <<'END_OF_FILE'
XADLookUp (c) 1989 by Christoper A. Wichura
X		(caw@miroc.chi.il.us or u12401@uicvm.uic.edu)
X
XThis program is copyrighted by me.  However, it is freely redistributable
Xso long as no charge is placed on the receiver.  The only exception to
Xthis being the cost of media and/or postage.
X
XThis software is presented as is.  Any damage or loss of money caused by
Xits use is the sole responsibility of the one using it.  I can not and will
Xnot be held accountable.
X
XNow that is out of the way (would some layer type tell me just how
X`official' that is, anyway?) lets get on with the nitty gritty.
X
XThis program is based on the GetAutoDoc command written by Peter Cherna for
Xhis DevKit.  This was a sorely needed program and I was quite happy to see
Xit at first.  However, I noticed several flaws in it and eventually decided
Xto re-write it.  The result is ADLookUp and its index generator
XADBuildIndex.
X
XThe main problems I had with GetAutoDoc were:
X
X	1) It stored its index on disk in a directory located within your
X	   AUTODOC: path.  This resulted in a fair amount of disk grinding
X	   any time you wanted to look something up.
X
X	   This was solved by making the index a shared library.  The first
X	   time ADLookUp is run it will load the index.  From then on, the
X	   index will remain memory resident until the op system gets into
X	   a memory crunch situation at which point the index will be
X	   dumped (unless, of course, ADLookUp is running and has it open
X	   at the time).  Thus, subsequent calls to ADLookUp are extremely
X	   fast at locating functions.
X
X	2) If you had more than one occurance of a function and asked
X	   GetAutoDoc to find it, GAD would only return the first occurance
X	   of it in its index files.  ADLookUp's index structure has been
X	   designed to handle multiple occurances of functions.  On my
X	   system, ADBuildIndex reports 52 such collisions so this is a
X	   handy addition.
X
X	3) GetAutoDoc only scanned autodoc files in your AUTODOC: path.
X	   ADBuildIndex allows you to give it as many paths as you want
X	   (with AUTODOC: being the default) and will recursively decend
X	   each one looking for autodoc files.
X
XBoth ADLookUp and ADBuildIndex require arp.library v39+.  They are both
Xfully residentable (though the need to make ADBuildIndex resident is
Xbeyond me...).
X
XADLookUp takes the following command line options:
X
XADLookUp <func1> <func2> ... <funcN> [TO <outfile>] [OPT B|C]
X
X	You can scan for as many functions as you want on the same
X	command line.  Wildcards are not permitted, though.  Function
X	names are not case sensitive.
X
X	The TO option allows you to specify an output target.  For
X	example, I modified Peter's LookUp CED script to use ADLookUp
X	and changed the redirection command to a TO command.  This command
X	was added for instances where ADLookUp might be started from some
X	task that doesn't understand redirection.  You are welcome to use
X	>outfile instead of TO, if you wish.
X
X	OPT B causes a banner to be printed before each function is
X	      listed.
X
X	OPT C causes ADLookUp to print the index creation date as stored
X	      in the index file.  Using this option will cause all other
X	      options to be ignored.  No function lookups will be done.
X
X	Note that ADLookUp follows the same method as GetAutoDoc for
X	returning error messages.  It places a dash followed by a space
X	as the first two character of the first line output.  This was
X	done for compatibility reasons.
X
X	Pressing CTRL-C will break ADLookUp.  If multiple functions are
X	being scanned, pressing CTRL-D will abort printing the current
X	function and go to the next one.
X
XADBuildIndex takes the following command line options:
X
XADBuildIndex <dir1> <dir2> ... <dirN> [VERBOSE] [NOEXPAND]
X
X	Each directory specified will be used as the root of a recursive
X	decent function to look for any and all autodoc files.  If not
X	specified, ADBuildIndex will default to AUTODOCS:.
X
X	VERBOSE prints plenty more info then you probably need.  Useful
X	for determining how far ADBuildIndex has gotten through an
X	AutoDoc file if a scan error occurs, though.
X
X	NOEXPAND tells ADBuildIndex not to expand the root dirs to their
X	full path specification.  By default, ADBuildIndex will convert
X	things such as AUTODOCS: or DF0: into full paths to prevent it from
X	looking at bogus disks (for example, if references were to DF0:
X	and you had the wrong disk in DF0: then ADLookUp wouldn't be able
X	to find the correct autodoc file).
X
X	ADBuildIndex is smart about name storage.  No path name, function
X	name, etc, will be duplicated.  This also helps to cut down on
X	the size of the index file tremendously (this is something that
X	GetAutoDoc did not do as well).  After all, why have 50+ copies of
X	`intuition.library' when you only need one?
X
X	Please remember that shared libraries are not automatically dumped
X	by the system when they are closed.  If you run ADBuildIndex and
X	then copy the new index file to your LIBS: dir it will not be used
X	automatically.  You should do something like FLUSHLIBS (from 
X	WorkBench hidden menu) or some such CLI equivalent to get rid of
X	the old copy in memory.
X
XWhen ADBuildIndex is run it will create an assembler file in your current
Xdurectory.  On my system (627 autodoc functions with 52 collisions) this
Xfile is about 90k in size.  It must be assebled into the actual shared
Xlibrary.  I have used both the PD a68k and commercial CAPE 68k v2 to
Xassemble this file with no problems.  The Lattice asm command complains
Xabout one line in this file, however.
X
XTo assemble the output file:
X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
X	A68k AutoDocIndex.a -iINCLUDE:
Xor	CASM -a AutoDocIndex.a -o AutoDocIndex.o -iINCLUDE:
X
Xthen	Blink AutoDocIndex.o to LIBS:AutoDocIndex.library lib lib:amiga.lib
X	      nd sc sd
X
X
XA future goal for ADBuildIndex is to directly output the library.  However,
XI have to figure out how to handle 3700+ relocs first :-).
X
XI have included Lattice source code for both ADLookUp and ADBuildIndex.
XHowever, to compile these programs you will need the ARP programmers kit
X(for the includes and glue code) as well as TXTtoOBJ (another small utility
XI wrote).  The included lmkfile will generate the modules for you.  Manx
Xusers will have to putz with the code to get it to work.
X
XA word about the index library:
X
X	The library was designed to be expandable.  ADLookUp calls
X	functions in the library to actually look up a function name and
X	scan for any collisions.  The scan is performed BY THE LIBRARY and
X	not ADLookUp.  Thus, if a more efficient format is found (and the
X	way it is now is not that terrific) then ADLookUp does not need
X	to be changed.
X
X	The library also has a FreeIndex function in it that is called
X	by ADLookUp when it is done with the index node.  This is to
X	allow future libraries to do cleanup on a function.  For example,
X	if the library stores all text compressed then it would have to
X	allocate a small chunk of memory to store the uncompressed form
X	that ADLookUp wants.  The FreeIndex hook would then be used to
X	free this chunk of memory afterwards to prevent ADLookUp from
X	sucking away all free memory.  Currenlty this function does nothing
X	except return zero.
X
X	Note that ADLookUp is __NOT__ allowed to modify any field passed
X	to it in the index node, or the index node itself.  If you want
X	to modify ADLookUp and need to play with the returned strings
X	you __MUST__ copy them to your own data space first!
X
X	The file specification for the autodoc file in IndexNodes is
X	compriesed of two parts:  the path and the basename (see the
X	source code for the actual structure definition).  People
X	wishing to create their own ADBuildIndex must insure that the
X	path contains any trailing characters (i.e., '/' or ':') needed
X	to allow for a simple strcat() option to be used to tack the
X	basename onto the path.
X
X	The GetFirstIndex() routine should use a static amount of stack
X	space.  ADLookUp will run with a 2k stack (provided it is launched
X	by the ARP, which checks for its Resident Program Tag).  Using a
X	recursive decent into an index tree will more than likely blow
X	the top off ADLookUp's stack.  Take a look at the function in
X	the current library for an example of how to search a tree without
X	using much stack.
X
X	That is the major notes.  The rest you can probably figure out
X	by looking at the code.
X
XChris Wichura,
X1/31/90
END_OF_FILE
if test 8325 -ne `wc -c <'readme'`; then
    echo shar: \"'readme'\" unpacked with wrong size!
fi
# end of 'readme'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.