/* dump.c -- routines to call od on some elts */
#include "he.h"

int HEdump(cmd)
    HE_CMD *cmd;
{
    register int i;
    int offset = 0;
    char *format = "-o";
    int length = 0;		/* zero is special, means all */

    for (i = 1; i < cmd->argc; i++)
	if (cmd->argv[i][0] == '-')
	    switch (findOpt(cmd->argv[i] + 1))
	    {
	    case HE_HELP:
		puts("dump [-offset <offset>] [-length <len>]"); 
		puts("\t[-decimal|-octal|-hexidecimal|-float|-ascii]");
		puts("\tOd the present element");
		puts("\t-offset\t\tStart offset");
		puts("\t-length\t\tLength to look at");
		puts("\t-decimal\tDecimal format");
		puts("\t-octal\t\tOctal format");
		puts("\t-hexidecimal\tHexidecimal format");
		puts("\t-float\t\tFloat format");
		puts("\t-ascii\t\tAscii format");
		return HE_OK;
	    case HE_OFFSET:
		offset = atoi(cmd->argv[++i]);
		break;
	    case HE_LENGTH:
		length = atoi(cmd->argv[++i]);
		if (length <= 0)
		{
		    fprintf(stderr,"Illegal length: %s, ignored.\n",
			    cmd->argv[i]);
		    length = 0;
		}
		break;
	    case HE_DECIMAL:
		format = "-d";
		break;
	    case HE_OCTAL:
		format = "-o";
		break;
	    case HE_HEX:
		format = "-h";
		break;
	    case HE_FLOAT:
		format = "-f";
		break;
	    case HE_ASCII:
		format = "-a";
		break;
	    case HE_NOTFOUND:
		unkOpt(cmd->argv[i]);
		return HE_FAIL;
	    case HE_AMBIG:
		ambigOpt(cmd->argv[i]);
		return HE_FAIL;
	    default:
		irrOpt(cmd->argv[i]);
		return HE_FAIL;
	    }
	else
	{
	    unkArg(cmd->argv[i]);
	    return HE_FAIL;
	}
    return dump(length, offset, format);
}

/* Run od on a segment of the current data element
 */
int dump(length, offset, format)
    int length;			/* length of segment to look at */
    int offset;			/* offset from start of data element */
    char *format;		/* od arg, e.g. -x for hexidecimal */
{
    int eltLength;
    char *data;
    char *tmpFile;

    if (!fileOpen())
    {
	noFile();
	return HE_FAIL;
    }

    eltLength = getElement(he_currDesc, &data);
    if (eltLength <= 0)
    {
	fprintf(stderr, "Unable to get element.\n");
	return HE_FAIL;
    }

    /* adjust the offset, negative offset implies starting from end. then
       check to see if offset is in range */
    if (offset < 0)
	offset = eltLength + offset;
    if (offset < 0 || offset > eltLength)
    {
	fprintf(stderr,"Illegal offset. Setting offset to 0.\n");
	offset = 0;
    }
    /* adjust the length if it falls outside */
    if (length == 0 || length > (eltLength - offset))
	length = eltLength - offset;

    /* get a temp file name to put the data for od to dump */
    getTmpName(&tmpFile);
    if (writeToFile(tmpFile, data + offset, length) < 0)
    {
	fprintf(stderr, "Unable to complete dump.\n");
	return HE_FAIL;
    }

    /* do an od on the tmp file */
    od(format, tmpFile);

    /* clean up */
    removeFile(tmpFile);
    free(data);
    free(tmpFile);

    return HE_OK;
}

/* end of dump.c */
