/*
** libshow.c
**
** Libraries and Devices Manager: ShowLibDev()
**
** $Id: libshow.c,v 3.0 94/08/09 17:30:04 GF Exp Locker: GF $
**
**************************************************************************
**
** Copyright © 1994 by Gabriele Falcioni. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** For inquiries, comments, donations, bug reports, write to:
**
** Gabriele Falcioni
** via E. Cialdini, 50
** I-60122 Ancona
** ITALY
**
*/

#include <string.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/resident.h>
#include <exec/libraries.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/dosasl.h>

#include <proto/dos.h>
#include <proto/exec.h>

#include <usrh/filefinder.h>
#include "libman.h"

/* --- My favourite macros -------------------------------------------- */

#define STDMEM (MEMF_PUBLIC|MEMF_CLEAR)

#define ConStruct(type)		((type *)AllocMem(sizeof(type),STDMEM))
#define DiStruct(ptr)		FreeMem((ptr),sizeof(*(ptr)))
#define ClearStruct(ptr)	memset((ptr),0,sizeof(*(ptr)))

#ifndef FOREVER
#define FOREVER for (;;)
#endif

#ifndef STREQ
#define STREQ(s1,s2) (!strcmp((s1),(s2)))
#endif

/* -------------------------------------------------------------------- */

/*
 * NAME
 * print_ldnode_short -- prints Library node to stdout (short)
 *
 * INPUT
 * a pointer to Library node.
 *
 * RESULT
 * none.
 */

static VOID print_ldnode_short(register struct Library *ldnode)
{
	Printf(" %-30s %2ld.%ld\t(%ld user%s)\n",
		ldnode->lib_Node.ln_Name,
		ldnode->lib_Version,ldnode->lib_Revision,
		ldnode->lib_OpenCnt,
		(ldnode->lib_OpenCnt == 1 ? "" : "s")
	);
}

/*
 * NAME
 * print_ldnode_long -- prints Library node to stdout (long)
 *
 * INPUT
 * a pointer to Library node.
 *
 * RESULT
 * none.
 */

static void print_ldnode_long(register struct Library *ldnode)
{
	Printf("\nName: %s\n",
		ldnode->lib_Node.ln_Name);

	Printf("Version: %ld\tRevision: %ld\tPriority: %ld\n",
		ldnode->lib_Version,
		ldnode->lib_Revision,
		ldnode->lib_Node.ln_Pri);

	Printf("Vectors: %ld\tOpenCount: %ld",
		ldnode->lib_NegSize/6,
		ldnode->lib_OpenCnt);

	if (ldnode->lib_Flags & LIBF_SUMUSED)
		Printf("\tCheckSum: 0x%08x",ldnode->lib_Sum);

	if (ldnode->lib_Flags & ~LIBF_SUMUSED) {
		Printf("\nStatus:");
		if (ldnode->lib_Flags & LIBF_SUMMING) Printf(" LIBF_SUMMING");
		if (ldnode->lib_Flags & LIBF_CHANGED) Printf(" LIBF_CHANGED");
		if (ldnode->lib_Flags & LIBF_DELEXP)  Printf(" LIBF_DELEXP");
	}

	Printf("\nId: \"%s\"\n",ldnode->lib_IdString);
}

/*
 * NAME
 * ShowLibDev -- display matching nodes of libraries or devices list
 *
 * SYNOPSIS
 * rc = ShowLibDev(names,type,full);
 *
 * LONG ShowLibDev(UBYTE **,UBYTE,BOOL);
 *
 * FUNCTION
 * It prints to stdout all the matching nodes of the libraries or
 * devices list. This function accepts standard AmigaDOS patterns.
 * The output form can be a simple list (short form) or a complete dump
 * of matching nodes (long form).
 *
 * INPUTS
 * names - a pointer to an array of pointers to lib/dev names. Standard
 *         AmigaDOS patterns accepted. The array must be NULL terminated.
 * type  - the list type: NT_LIBRARY or NT_DEVICE.
 * full  - if TRUE the long form is printed else short form.
 *
 * RESULTS
 * rc - level of failure:
 *      RETURN_OK		list successfully displayed,
 *      RETURN_ERROR user break and so on,
 *      RETURN_FAIL	total failure.
 *      Error messages will be printed (if required) to stdout.
 */

#define SAFE_SET_RC(rc,level) if ((rc) < (level)) (rc) = (level)

LONG ShowLibDev(UBYTE **names,UBYTE type,BOOL full)
{
	LONG rc;
	struct List *clone;
	struct NodeMatcher *nm;

	rc = 0;

	if (clone = CloneLibDev(type)) {
		if (nm = CreateNodeMatcher(names,clone)) {
			register struct Library *libnode;
			LONG nodes;

			/*
			 * Print banner.
			 */

			Printf("Current %s List:\n",
				(type == NT_LIBRARY ? "Library" : "Device"));

			/*
			 * Loop for all patterns and display matching nodes.
			 */

			nodes = 0;
			while (libnode = (struct Library *)MatchNodes(nm)) {
				if (full) print_ldnode_long(libnode);
				else      print_ldnode_short(libnode);

				++nodes;
			}

			if (IoErr()) {
				PrintFault(IoErr(),NULL);
				rc = RETURN_ERROR;
			}

			if (!rc && !nodes) Printf(" [no nodes]\n");

			DeleteNodeMatcher(nm);
		} else {
			PrintFault(ERROR_NO_FREE_STORE,NULL);
			rc = RETURN_ERROR;
		}

		FreeVec(clone);	/* free clone */
	} else {
		PrintFault(ERROR_NO_FREE_STORE,NULL);
		rc = RETURN_FAIL;
	}

	return rc;
}
