Blob Blame History Raw
/*****************************************************************************/
/*  dalist: a zero-dependency book-keeping library                           */
/*  Copyright (C) 2013--2021  SysDeer Technologies, LLC                      */
/*  Released under GPLv2 and GPLv3; see COPYING.DALIST.                      */
/*****************************************************************************/

#include <dalist/dalist.h>
#include "dalist_impl.h"

dalist_api
int dalist_debug_setup(
	struct dalist_ex *	dlist,
	struct dalist_debug *	dlist_debug,
	enum dalist_dbgenv	dbgenv,
	dalist_sprintf *	pfn_sprintf,
	dalist_write *		pfn_write,
	dalist_write_file *	pfn_write_file)
{
	if (dlist)
		/* in case we fail */
		dlist->debug = 0;
	else
		return DALIST_ELIST;

	if (!dlist_debug)
		return DALIST_EDEBUGSTRUCT;
	else if (!pfn_sprintf)
		return DALIST_EDEBUGSPRINTF;

	switch (dbgenv) {
		case DALIST_DEBUG_ENV_POSIX:
			if (!pfn_write)
				return DALIST_EDEBUGWRITE;
			break;

		case DALIST_DEBUG_ENV_NT:
			if (!pfn_write_file)
				return DALIST_EDEBUGWRITEFILE;
			break;

		default:
			return DALIST_EDEBUGENV;
	}

	dlist_debug->dbgenv        = dbgenv;
	dlist_debug->sprintf       = pfn_sprintf;
	dlist_debug->write         = pfn_write;
	dlist_debug->zw_write_file = pfn_write_file;

	dlist->debug = dlist_debug;

	return DALIST_OK;
}


static const char dalist_fmt_header_32[] =
	"dlist:\t\t0x%08x\n"
	"dlist->head:\t0x%08x\n"
	"dlist->tail:\t0x%08x\n\n";

static const char dalist_fmt_header_64[] =
	"dlist:\t\t0x%016x\n"
	"dlist->head:\t0x%016x\n"
	"dlist->tail:\t0x%016x\n\n";

static const char dalist_fmt_node_32[] =
	"node: 0x%08x\t"
	"prev: 0x%08x\t"
	"next: 0x%08x\t"
	"any:  0x%08x\t\n";

static const char dalist_fmt_node_64[] =
	"node: 0x%016x\t"
	"prev: 0x%016x\t"
	"next: 0x%016x\t"
	"any:  0x%016x\t\n";

static const char * dalist_fmt_headers[2] = {
	dalist_fmt_header_32,
	dalist_fmt_header_64
};

static const char * dalist_fmt_nodes[2] = {
	dalist_fmt_node_32,
	dalist_fmt_node_64
};


static int dalist_dbg_write_posix(
	struct dalist_ex *	dlist,
	intptr_t		fildes_or_hfile,
	const void *		buf,
	size_t			nbyte)
{
	int		fildes;
	dalist_write *	pfn_write;
	ssize_t		bytes_written;

	fildes = (int)fildes_or_hfile;
	pfn_write = (dalist_write *)dlist->debug->write;

	bytes_written = pfn_write(fildes,buf,nbyte);

	if (bytes_written < 0)
		return DALIST_EDEBUGENV;

	else if (bytes_written == (ssize_t)nbyte)
		return DALIST_OK;

	else
		return DALIST_EDEBUGENV;
}


static int dalist_dbg_write_nt(
	struct dalist_ex *	dlist,
	intptr_t		fildes_or_hfile,
	const void *		buf,
	size_t			nbyte)
{
	void *			hfile;
	struct dalist_iosb	iosb;
	dalist_write_file *	pfn_write_file;

	hfile          = (void *)fildes_or_hfile;
	pfn_write_file = (dalist_write_file *)dlist->debug->zw_write_file;

	return pfn_write_file(
		hfile,
		(void *)0,
		(void *)0,
		(void *)0,
		&iosb,
		(void *)buf,
		(uint32_t)nbyte,
		(int64_t *)0,
		(uint32_t *)0);
}


dalist_api
int dalist_debug_print(
	struct dalist_ex *	dlist,
	intptr_t		fildes_or_hfile)
{
	const char *		fmt_header;
	const char *		fmt_node;
	char			dbg_buf[128];
	intptr_t		nbyte;

	int			status;
	struct dalist_node *	node;
	dalist_sprintf *	dbg_sprintf;
	dalist_dbg_write *	dbg_write;

	if (!dlist)
		return DALIST_ELIST;
	else if (!dlist->debug)
		return DALIST_EDEBUGENV;

	/* initial setup */
	dbg_sprintf = (dalist_sprintf *)dlist->debug->sprintf;
	fmt_header  = dalist_fmt_headers[(sizeof(size_t)-4)/4];
	fmt_node    = dalist_fmt_nodes[(sizeof(size_t)-4)/4];

	if (dlist->debug->dbgenv == DALIST_DEBUG_ENV_POSIX)
		dbg_write = dalist_dbg_write_posix;
	else if (dlist->debug->dbgenv == DALIST_DEBUG_ENV_NT)
		dbg_write = dalist_dbg_write_nt;
	else
		dbg_write = 0;

	if ((!dbg_sprintf) || (!dbg_write))
		return DALIST_EDEBUGENV;

	/* print list header */
	nbyte = dbg_sprintf((char *)dbg_buf,fmt_header,dlist,dlist->head,dlist->tail);

	if (nbyte < 0)
		return DALIST_EDEBUGENV;

	status = dbg_write(dlist,fildes_or_hfile,dbg_buf,nbyte);

	if (status != NT_STATUS_SUCCESS)
		return DALIST_EDEBUGENV;

	/* print node information */
	status = DALIST_OK;
	node   = (struct dalist_node *)dlist->head;

	while (node && (status == DALIST_OK)) {
		/* create output line */
		nbyte = dbg_sprintf(
			(char *)dbg_buf,
			fmt_node,
			node,
			node->prev,
			node->next,
			node->any);

		if (nbyte < 0)
			return DALIST_EDEBUGENV;

		/* write output line */
		status = dbg_write(
			dlist,
			fildes_or_hfile,
			dbg_buf,
			nbyte);

		node = node->next;
	}

	return DALIST_OK;
}