Path: utzoo!attcan!uunet!husc6!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ain
From: ain@j.cc.purdue.edu (Patrick White)
Newsgroups: comp.sources.amiga
Subject: disklib (sources 1 of 1)
Keywords: disk libraries, compiled.
Message-ID: <7305@j.cc.purdue.edu>
Date: 27 Jun 88 13:00:20 GMT
Organization: PUCC Land, USA
Lines: 704
Approved: ain@j.cc.purdue.edu	(Patrick White)

Submitted by:	snyderw@life.pawl.rpi.edu
Summary:	Generate disk library listings from $$DES$$ files in the directories.
Poster Boy:	Patrick White	(ain@j.cc.purdue.edu)
Archive Name:	sources/amiga/volume5/disklib.s.sh.Z
Tested.
 
NOTES:
   This is really two programs -- lib and tolib.
   The $$DES$$ file for these programs is in the docs, along with a brief
description of the format of a $$DES$$ file (basically none).
 
 
-- Pat White   (co-moderator comp.sources/binaries.amiga)
ARPA/UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM  PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906
 
========================================
 
#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	lib.c
#	tolib.c
# This archive created: Wed Jun 22 12:20:29 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting lib.c '(12961 characters)'
cat << \SHAR_EOF > lib.c
/***************************************************************
*
*			Lib.c
*
*		Disk Library Documentation System
*			Main Program
*
*	By Wilson Snyder		(c) January 1988
*
****************************************************************
*
*	NOTICE:
*
*	This program was written as a service to the amiga
*	users.  This program may be used by all parties, including
*	sale (see below) as long as the author's name and address
*	remains intact in the program and documentation.
*	Distribution of this program by parties selling it
*	as part of a commercial for-profit package of over $10
*	must contact the address below before such a package is sold.
*
*	I make no warranties over this program, performance,
*	etc.  And any costs incurred by this program, or its
*	actions are placed on the user.
*
*	PLEASE FORWARD INPROVEMENTS MADE TO THIS PROGRAM TO:
*
*	Wilson Snyder, 15 Davis Parkway, South Burlington, VT 05403
*
****************************************************************
*
*	AddName and base for Process taken from the TSIZE
*	utility written by the excellent work of the
*	Software Distillery.
*
****************************************************************/

#include "libraries/dosextens.h"
#include "ctype.h"
#include "stdio.h"

#define VERSION	"AMIGA-LIB.  Version 1.0.2.  By Wilson Snyder"
#define DESC "$$DES$$"

#define PERSUB	8	/* Characters to indent per subdirectory */
#define INFOIND 8	/* Indent for description and filesize */
#define RM	75	/* Right margin */
#define LM	0	/* Left margin */
#define TM	1	/* Top margin */
#define HM	2	/* Header margin (lines after header) */
#define LINES	60	/* Lines per page */

BPTR	Lock();		/* Define functions... */
BOOL	Examine();
BOOL	ExNext();

char	path [256];		/* Current search path */
char	header [80];		/* Header for top line */
BOOL	prtsize = FALSE;	/* Print the path size information */
BOOL	prtheader = FALSE;	/* Print the header and page breaks */

struct Sortem {		/* Linked list for insertion sort of directory names */
	char	FileName[108];	/* Directory name */
	struct Sortem *Next;	/* Pointer to next */
	};

/***************************************************************
*			ADDNAME
*
*	Add filename to the end of the current path.
*
*	Routine taken from from TSIZE utility by the Software Distillery.
***************************************************************/

int	AddName(name, len)
	register char *name;
	int len;
	{
	register char *p;	/* current position in path */
	register int i = 0;	/* added length counter */
	char ch;		/* last character of current path */

	p = path + len;

	/* add a slash between path and name if legal */
	if (len != 0 && (ch = path[len-1]) != '/' && ch != ':') {
		*p++ = '/';
		i++;
		}

	/* copy name to end of path (including null terminator) */
	while (*p++ = *name++) i++;

	/* return new length of path */
	return (len + i);
	}


/***************************************************************
*			FILECMP
*	Compare two filenames for sort routine (case insensitive.)
***************************************************************/

int	filecmp(a,b)
	char *a,*b;
	{
	for (;toupper(*a)==toupper(*b);a++,b++)
		if (*a=='\0') return (0);
	return (toupper(*a)-toupper(*b));
	}


/***************************************************************
*			INDENT
*	Indent a number of spaces.  Outputted to stdout.
***************************************************************/

void	Indent(num)
	int num;
	{
	while (num--)	putchar (' ');
	}

/***************************************************************
*			HEADER
*	Print header every so many lines.
***************************************************************/

void	Header(inc)
	int inc;
	{
	static int linecount;		/* Number of lines down */
	static int page;		/* Current page number */
	int t;				/* Temp */

	if (inc)
		linecount += inc;
	else	{
		/* 0 increment resets information */
		linecount = 0;
		page = 0;
		}

	if (linecount>LINES && prtheader) {
		/* Time to print the header */
		putchar ('\f');
		page++;
		for (t=TM;t;t--)	putchar ('\n');
		printf (header,page);
		for (t=HM;t;t--)	putchar ('\n');
		linecount = TM + HM + 1;
		}
	}


/***************************************************************
*			ROOT
*	Print information for the page header
***************************************************************/

BOOL	Root()
	{
	struct FileInfoBlock *info;	/* pointer to file info */
	BPTR lock;			/* pointer to file lock */
	int t,loc;			/* temp stuff */

	/* allocate an info block (must be longword alligned) */
	if (!(info = (struct FileInfoBlock *)
		AllocMem(sizeof(struct FileInfoBlock), 0))) {
			printf ("Out of memory.\n");
			return (TRUE);
			}

	/* try to obtain lock on current file */
	if (!(lock = Lock(path, ACCESS_READ))) {
		printf ("Invalid file or directory, '%s'.\n", path);
		FreeMem(info, sizeof(struct FileInfoBlock));
		return (TRUE);
		}

	/* get information on file or directory associated with lock */
	if (!Examine(lock, info)) {
		printf ("Error examining locked file or directory.\n");
		UnLock(lock);
		FreeMem(info, sizeof(struct FileInfoBlock));
		return (TRUE);
		}

	/* Make sure user specified a directory, not a file */
	if (info->fib_DirEntryType <= 0) {
		printf ("Must specify a directory, not a file.\n");
		UnLock(lock);
		FreeMem(info, sizeof(struct FileInfoBlock));
		return (TRUE);
		}

	/* Build Header line (will be used with printf) */
	loc = 0;
	for (t=LM;t;t--)	header[loc++] = ' ';
	strcpy (&header[loc], "Page %-4d");
	loc += 9;
	for (t=RM-loc-strlen(info->fib_FileName);t;t--)	header[loc++] = ' ';
	strcpy (&header[loc],info->fib_FileName);
	loc += strlen(info->fib_FileName);
	header[loc++] = '\n';
	header[loc] = '\0';

	/* Initalize header printer, then force header printing */
	Header (0);
	Header (LINES+2);

	UnLock(lock);
	FreeMem(info, sizeof(struct FileInfoBlock));
	return (FALSE);
	}


/***************************************************************
*			BOTTOM
*	Display size information at bottom of directory.
***************************************************************/

void	Bottom (depth,size,found)
	int depth;
	long size;
	BOOL found;
	{
	if (prtsize) {
		Indent (depth*PERSUB+INFOIND+LM);
		printf ("Total size %ld bytes.\n", size);
		if (found) printf ("\n");
		Header (2);
		}
	}

/***************************************************************
*			DISPLAY
*	Display information from the DESC file in the directory.
***************************************************************/

BOOL	Display (depth,dirname)
	int depth;
	char *dirname;
	{
	FILE *desc;		/* DESCription file info */
	BOOL found;		/* Found a description file */
	int lineloc;		/* Location on the output line */
	int wordlen;		/* Length of word in the buffer */
	char wordstore[RM+10];	/* Storage for current word */
	BOOL Cont;		/* & encountered, ignore return */
	BOOL Long;		/* Long line/word just printed */
	char ch;		/* Character from file */
	int t,lm;		/* temp */

	/* Print directory name */
	Header (2);
	Indent (depth*PERSUB+LM);
	printf ("%s\n", dirname);

	/* Add DESC filename to path, attempt to open the file */
	t = strlen(path);
	AddName (DESC,t);
	found = ((desc=fopen(path,"r"))!=0);

	/* If found, justify the file on the way out */
	if (found) {
		lm = depth*PERSUB+INFOIND+LM;
		lineloc = lm;
		Indent (lm);
		wordlen = 0;
		Cont = FALSE;
		Long = FALSE;
		/* Process one character at a time */
		while ((ch=getc(desc))!=EOF) {
			/* Ignore return if proceded by a & */
			if ((ch=='\n') && Cont) {
				Cont = FALSE;
				continue;
				}
			if (Cont) {	/* & not proceded by a return */
				wordstore[wordlen++] = '&';
				Cont = FALSE;
				}
			/* Dump out the current word */
			if (ch==' ' || ch=='\n') {
				wordstore[wordlen] = '\0';
				printf ("%s ",wordstore);
				lineloc += wordlen + 1;
				wordlen = 0;
				if (Long || ch=='\n') {
					putchar ('\n');
					Header(1);
					Indent (lm);
					lineloc = lm;
					Long = FALSE;
					}
				continue;
				}
			/* Force return if line goes over right margin */
			if (((wordlen+lineloc)>RM) || (wordlen>(RM-lm))) {
				if (wordlen>(RM-lm)) {
					wordstore[wordlen] = '\0';
					printf ("%s",wordstore);
					wordlen = 0;
					Long = TRUE;
					}
				putchar ('\n');
				Header(1);
				Indent (lm);
				lineloc = lm;
				}
			/* Check for continuation character */
			if (ch=='&')	Cont = TRUE;
			else	wordstore[wordlen++] = ch;
			}
		fclose (desc);
		/* Dump out any remaining word in the buffer */
		if (wordlen) {
			wordstore[wordlen] = '\0';
			puts (wordstore);
			putchar ('\n');
			Header (1);
			lineloc=0;
			}
		if (lineloc>lm)	putchar('\n');
		putchar('\n');
		}

	/* Restore path, return status if file was found */
	path[t] = '\0';
	return (found);
	}


/*************************************************************
*			PROCESS
*
*	Find the size of a directory tree by adding the sizes
*	of all files in the directory and all of its subdirectories.
*
*	General directory searching concept taken from TSIZE
*	utility by the Software Distillery.
************************************************************/

long	Process(len,depth)
	int len;	/* Length of path name */
	int depth;	/* Number of directories down */
	{
	struct FileInfoBlock *info = NULL;	/* pointer to file info */
	struct Sortem *sort_top = NULL;		/* top of sort list */
	struct Sortem *sort_cur = NULL;		/* current sort list loc */
	struct Sortem *sort_tmp = NULL;		/* current sort temp loc */
	struct Sortem *sort_last= NULL;		/* last sort temp loc */
	long size = 0;				/* running total of file size */
	BPTR lock;				/* pointer to file lock */
	BOOL found;				/* found DESC file */

	/* Try to obtain lock on current directory */
	if (!(lock = Lock(path, ACCESS_READ))) {
		printf ("Invalid directory, '%s'.\n", path);
		goto EXIT;
		}

	/* Allocate an info block (must be longword alligned) */
	if (!(info = (struct FileInfoBlock *)
		AllocMem(sizeof(struct FileInfoBlock), 0))) {
			printf ("Out of memory.\n");
			goto EXIT;
			}

	/* Get information on file or directory associated with lock */
	if (!Examine(lock, info)) {
		printf ("Error examining locked directory.\n");
		goto EXIT;
		}

	/* This should not happen, but... */
	if (info->fib_DirEntryType <= 0)  {
		printf ("Locked a file, not directory.\n");
		goto EXIT;
		}

	/* Display top of directory header */
	found = Display (depth,info->fib_FileName);

	/* Read this directory */
	while (ExNext(lock, info)) {
		/* This is a directory */
		if (info->fib_DirEntryType > 0)	{
			/* sub-directory, allocate sortem node */
			if (!(sort_cur = (struct Sortem *)
					AllocMem(sizeof(struct Sortem), 0))) {
				printf ("Out of memory.\n");
				break;
				}
			strcpy(sort_cur->FileName,info->fib_FileName);
			sort_cur->Next = NULL;

			/* Alphabetical insertion sort */
			/* Find insertion location for new node */
			for (sort_tmp = sort_top; sort_tmp; 
				sort_tmp = sort_tmp->Next) {
				if (filecmp(sort_tmp->FileName,info->fib_FileName)>0)
					break;
				sort_last = sort_tmp;
				}

			/* Insert the node */
			if (sort_tmp==sort_top) {
				sort_cur->Next = sort_top;
				sort_top = sort_cur;
				}
			else	if (!sort_tmp) {
				sort_cur->Next = NULL;
				sort_last->Next = sort_cur;
				}
				else {
					sort_cur->Next = sort_last->Next;
					sort_last->Next = sort_cur;
					}
			sort_cur = NULL;
			}
		else 	/* found a file, just add size */
			size += info->fib_Size;
		}

	/* Transverse sorted list, process then deallocate the node */
	for (sort_tmp = sort_top; sort_tmp; sort_tmp = sort_last) {
		size += Process(AddName(sort_tmp->FileName, len),depth+1);
		sort_last = sort_tmp->Next;
		FreeMem(sort_tmp, sizeof(struct Sortem));
		}

	/* Repair path */
	path[len] = '\0';

	/* Print bottom of directory information */
	Bottom (depth, size, found);

	EXIT:
	if (info) FreeMem(info, sizeof(struct FileInfoBlock));
	if (lock) UnLock(lock);
	return(size);
	}

/***************************************************************
*			MAIN
***************************************************************/

main(argc, argv)
	int argc;
	char *argv[];
	{
	int len;	/* Length of file name given on command line */
	int t;		/* Temp variable */

	/* Help information */
	if (argv[1][0]=='?') {
		printf ("%s\nUseage: %s [Read-Path] [-size]\n",
			VERSION, argv[0]);
		exit (0);
		}

	/* parse command line (len used as temp param counter) */
	for (len=1;len1)
		len = AddName(argv[1], 0);
	else	len = AddName(":", 0);

	/* Check root info, exit if invalid */
	if (Root()) return(20);

	/* Process root directory */
	(void)Process(len,0);

	EXIT:
	return(0);
	}
SHAR_EOF
if test 12961 -ne "`wc -c lib.c`"
then
echo shar: error transmitting lib.c '(should have been 12961 characters)'
fi
echo shar: extracting tolib.c '(4042 characters)'
cat << \SHAR_EOF > tolib.c
/***************************************************************
*
*			ToLib.c
*
*		Disk Library Documentation System
*		Convert README.list files to LIB system
*
*	By Wilson Snyder		(c) January 1988
*
****************************************************************
*
*	NOTICE:
*
*	This program was written as a service to the amiga
*	users.  This program may be used by all parties, including
*	sale (see below) as long as the author's name and address
*	remains intact in the program and documentation.
*	Distribution of this program by parties selling it
*	as part of a commercial for-profit package of over $10
*	must contact the address below before such a package is sold.
*
*	I make no warranties over this program, performance,
*	etc.  And any costs incurred by this program, or its
*	actions are placed on the user.
*
*	PLEASE FORWARD INPROVEMENTS MADE TO THIS PROGRAM TO:
*
*	Wilson Snyder, 15 Davis Parkway, South Burlington, VT 05403
*
***************************************************************/

#include "exec/types.h"
#include "stdio.h"

#define VERSION	"AMIGA-TOLIB.  Version 1.0.0.  By Wilson Snyder"

#define BRK	70	/* Where to break up long, continous lines */
#define BRKTIT	40	/* Where to break title */
#define	SPACEEQ	3	/* Spaces seperating filename and description */

void	main(argc, argv)
	int argc;
	char *argv [];
	{
	FILE *InFile,*OutFile;		/* Files for reading and writing */
	unsigned char cntr=0;		/* Insert line break every BRK chars */
	int spaces;			/* Number spaces encountered */
	int mode; /* 0=line begin, 1=space drop, 2=coping, 3=title extract */
	BOOL linelast;			/* Copied text on the last line */
	char ch;			/* Current read character */

	/* Print usage information */
	if (argv[1][0]=='?') {
		printf ("%s\nUseage: %s Input-File Output-File [header]\n",
			VERSION, argv[0]);
		exit (0);
		}

	/* Open input file */
	if (!(InFile = fopen (argv[1],"r"))) {
		printf ("Bad input file.\n");
		exit (0);
		}

	/* Open output file */
	if (!(OutFile = fopen (argv[2],"w"))) {
		printf ("Bad output file.\n");
		fclose (InFile);
		exit (0);
		}


	mode = 0;
	cntr = 0;
	linelast = FALSE;

	/* Begin the copy */
	while ((ch=getc(InFile))!=EOF) {
	    /* Newline, reset mode to 0, */
	    if (ch=='\n') {
		linelast = (mode==1 || mode==2);
		if (linelast) {
			/* output continuation if text printed on last line */
			putc(' ',OutFile);
			putc('&',OutFile);
			}
		putc (ch,OutFile);
		mode = 0;
		continue;
		}
		
	    switch (mode) {
		case 0:	/* Beginning of Line */
			cntr = 0;
			/* If begins with space or tab is a text line */
			if (ch==' ' || ch=='\t') {
				mode = 1;	/* Skip leading spaces */
				}
			else	{
				/* Otherwise is a new title */
				if (linelast)	putc ('\n',OutFile);
				if (argc>3)	{
					/* Print optional disk title */
					fputs (argv[3],OutFile);
					putc ('\n',OutFile);
					}
				spaces = 0;
				mode = 3;	/* Copy title */
				putc(ch,OutFile);
				}
			break;

		case 1:	/* Skipping leading spaces or tabs before text */
			if (ch==' ' || ch=='\t')	break;	/* drop it */
			putc (ch,OutFile);
			cntr = 1;
			mode = 2;	/* now copy remainder */
			break;

		case 2:	/* Coping to EOL */
			cntr++;
			if (cntr>BRK) {
				putc('&',OutFile);
				putc('\n',OutFile);
				cntr = 0;
				}
			putc (ch,OutFile);
			break;

		case 3:	/* Copying title until tab or several spaces */
			cntr++;
			/* count spaces, after SPACEEQ start text copy */
			if (ch==' ')
				spaces++;
			/* End of title, found a tab or line over length */
			if ((spaces>=SPACEEQ) || ch=='\t' || cntr>=BRKTIT) {
				putc ('\n', OutFile);
				mode = 1;	/* skip rest */
				break;
				}
			if (ch==' ') break;

			/* Write title info after stored spaces*/
			while (spaces--)	putc (' ', OutFile);
			spaces = 0;
			if (ch!=' ') putc (ch, OutFile);
			if (cntr>=BRKTIT)	mode = 1;	/* Chr limit */
			break;

		default:
			/* Bad state */
			printf ("Internal mode error\n");
			fclose (InFile);
			fclose (OutFile);
			exit(20);
		}
	    }

	/* All done. */
	fclose (InFile);
	fclose (OutFile);
	}
SHAR_EOF
if test 4042 -ne "`wc -c tolib.c`"
then
echo shar: error transmitting tolib.c '(should have been 4042 characters)'
fi
#	End of shell archive
exit 0