/*
 * Copyright (c) 1998,1999,2000
 *	Traakan, Inc., Los Altos, CA
 *	All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Project:  NDMJOB
 * Ident:    $Id: $
 *
 * Description:
 *
 */


#include "ndmlib.h"


/*
 * Media Entry (medent)
 *
 * [LABEL][+FILEMARKS][/NBYTES][@SLOT]
 *
 * LABEL is simple text and must be first.
 *
 * +FILEMARKS, /NBYTES, and @SLOT may occur in any order.
 *
 * FILEMARKS is a small decimal number and indicates
 * how many filemarks to skip when using the media.
 * 0 means begining of tape. If no +FILEMARKS is given,
 * 1 is used if LABEL is given, 0 otherwise.
 *
 * NBYTES indicates the maximum amount of data on the
 * media. This is a decimal number optionally followed
 * by a scale character (k, m, g).
 *
 * SLOT is the slot address in the tape robot. It is
 * the element address, not relative to the first
 * slot in the robot.
 */

int
ndmmedia_from_str (struct ndmmedia *me, char *str)
{
	char *		p;
	char *		q;
	int		c;

	NDMOS_MACRO_ZEROFILL (me);

	p = str;
	q = me->label;

	for (; *p; p++) {
		c = *p;
		if (c == '+' || c == '@' || c == '/')
			break;

		if (q < &me->label[NDMMEDIA_LABEL_MAX])
			*q++ = c;
	}
	*q = 0;

	if (q > me->label)
		me->valid_label = 1;

	while (*p) {
		c = *p;
		switch (c) {
		default:
			return -1;		/* what is this? */

		case '@':
			if (me->valid_slot)
				return -2;

			me->slot_addr = strtol (p+1, &p, 0);
			me->valid_slot = 1;
			break;

		case '+':
			if (me->valid_filemark)
				return -3;

			me->file_mark_offset = strtol (p+1, &p, 0);
			me->valid_filemark = 1;
			break;

		case '/':
			if (me->valid_n_bytes)
				return -4;

			me->n_bytes = ndmmedia_strtoll (p+1, &p, 0);
			me->valid_n_bytes = 1;
			break;
		}
	}

	return 0;
}

int
ndmmedia_to_str (struct ndmmedia *me, char *str)
{
	char *		q = str;

	*q = 0;

	if (me->valid_label) {
		strcpy (q, me->label);
		while (*q) q++;
	}

	if (me->valid_filemark) {
		sprintf (q, "+%d", me->file_mark_offset);
		while (*q) q++;
	}

	if (me->valid_n_bytes) {
		if (me->n_bytes == 0)
			sprintf (q, "/0");
		else if (me->n_bytes % (1024*1024*1024) == 0)
			sprintf (q, "/%lldG", me->n_bytes/(1024*1024*1024));
		else if (me->n_bytes % (1024*1024) == 0)
			sprintf (q, "/%lldM", me->n_bytes/(1024*1024));
		else if (me->n_bytes % (1024) == 0)
			sprintf (q, "/%lldK", me->n_bytes/(1024));
		else
			sprintf (q, "/%lld", me->n_bytes);
		while (*q) q++;
	}

	if (me->valid_slot) {
		sprintf (q, "@%d", me->slot_addr);
		while (*q) q++;
	}

	return 0;
}


static char *flag_yes_or_no (int f) { return (f) ? "Y" : "N"; }

int
ndmmedia_pp (struct ndmmedia *me, int lineno, char *buf)
{
    switch (lineno) {
    case 0:
	ndmmedia_to_str (me, buf);
	break;

    case 1:
	sprintf (buf, "valid label=%s filemark=%s n_bytes=%s slot=%s",
		flag_yes_or_no (me->valid_label),
		flag_yes_or_no (me->valid_filemark),
		flag_yes_or_no (me->valid_n_bytes),
		flag_yes_or_no (me->valid_slot));
	break;

    case 2:
	sprintf (buf, "media used=%s written=%s eof=%s eom=%s io_error=%s",
		flag_yes_or_no (me->media_used),
		flag_yes_or_no (me->media_written),
		flag_yes_or_no (me->media_eof),
		flag_yes_or_no (me->media_eom),
		flag_yes_or_no (me->media_io_error));
	break;

    case 3:
	sprintf (buf, "label read=%s written=%s io_error=%s mismatch=%s",
		flag_yes_or_no (me->label_read),
		flag_yes_or_no (me->label_written),
		flag_yes_or_no (me->label_io_error),
		flag_yes_or_no (me->label_mismatch));
	break;

    case 4:
	sprintf (buf, "fm_error=%s nb_determined=%s nb_aligned=%s",
		flag_yes_or_no (me->fmark_error),
		flag_yes_or_no (me->nb_determined),
		flag_yes_or_no (me->nb_aligned));
	break;

    case 5:
	sprintf (buf, "slot empty=%s bad=%s missing=%s",
		flag_yes_or_no (me->slot_empty),
		flag_yes_or_no (me->slot_bad),
		flag_yes_or_no (me->slot_missing));
	break;

    default:
	strcpy (buf, "<<INVALID>>");
	break;
    }

    return 6;
}

long long
ndmmedia_strtoll (char *str, char **tailp, int defbase)
{
	long long		val = 0;
	int			c;

	for (;;) {
		c = *str;
		if (c < '0' || '9' < c)
			break;
		val *= 10;
		val += c - '0';
		str++;
	}

	switch (c) {
	default:
		break;

	case 'k': case 'K':
		val *= 1024LL;
		str++;
		break;

	case 'm': case 'M':
		val *= 1024*1024LL;
		str++;
		break;

	case 'g': case 'G':
		val *= 1024*1024*1024LL;
		str++;
		break;
	}

	if (tailp) *tailp = str;

	return val;
}
