
/*
 * list.c
 *
 * (C) Copyright 1995 Archie L. Cobbs
 */

#include <stdio.h>
#include <assert.h>
#include "util.h"
#include "error.h"
#include "names.h"
#include "obj.h"
#include "asm.h"

/*
 * INTERNAL FUNTIONS
 */

	static	void		ShowLineNum(FILE *fp);
	static	void		ShowLoc(FILE *fp, int segment, unsigned offset);

/*
 * ListLine()
 *
 * List current line.
 *
 * Assumes no trailing newline in gLineBuf. Another assumption is
 * that gListBytes is true only when gSegrel.segment >= 0 (that is,
 * if we're showing emitted bytes we always show the current location).
 */

void
ListLine(FILE *fp)
{
	int		k, nbytes, extra;

/* Show line number */

	ShowLineNum(fp);

/* Annotate line with segment address if desired */

	if (gSegrel.segment >= 0)
		ShowLoc(fp, gSegrel.segment, gSegrel.offset);
	else
		fprintf(fp, "\t");

/* Compute number of bytes to show */

	if (!gListBytes)
		nbytes = extra = 0;
	else
	{

	/* Calculate difference in segment offset between before and after
	   the line was reduced by the parser (and bytes were emitted) */

		nbytes = gAddress[gSegrel.segment] - gSegrel.offset;

	/* Figure how much is "extra" subject to the state of .expand */

		if (nbytes > 4)
		{
			extra = nbytes - 4;
			nbytes = 4;
		}
		else
			extra = 0;
	}

/* Show a few bytes on the first line */

	for (k = 0; k < nbytes; k++)
	{
		fprintf(fp, "%02X", gSegBuffer[gSegrel.segment][gSegrel.offset++]);
		if (k < nbytes - 1)
			fprintf(fp, " ");
	}
	if (nbytes <= 1)
		fprintf(fp, "\t");
	fprintf(fp, "\t");

/* Now show the input line */

	fprintf(fp, "%s\n", gLineBuf);
	fflush(fp);

/* Show remaining bytes if expand is on */

	if (gExpand)
		while (extra)
		{
			ShowLineNum(fp);
			ShowLoc(fp, gSegrel.segment, gSegrel.offset);
			nbytes = extra;
			nbytes = (nbytes <= 8) ? nbytes : 8;
			extra -= nbytes;
			for (k = 0; k < nbytes; k++)
			{
				fprintf(fp, "%02X",
					gSegBuffer[gSegrel.segment][gSegrel.offset++]);
				if (k < nbytes - 1)
					fprintf(fp, " ");
			}
			fprintf(fp, "\n");
			fflush(fp);
		}
}

/*
 * ShowLineNum()
 */

static	void
ShowLineNum(FILE *fp)
{
	fprintf(fp, "%4d", gLineNumber);
	if (gLineNumber < 10000)
		fprintf(fp, " ");
}

/*
 * ShowLoc()
 */

static	void
ShowLoc(FILE *fp, int segment, unsigned offset)
{

/* Don't screw up alignment -- only show lower 16 bits */

	offset &= 0xFFFF;

/* Show segment and offset */

	fprintf(fp, "%c %04X ",
		segment == CodeSegment ? 'C' :
		segment == DataSegment ? 'D' :
		segment == BssSegment ? 'B' :
		segment == AbsSegment ? ' ' :
		'?', offset);
}

