#include <dos/dos.h>
#include <dos/rdargs.h>
#include <proto/dos.h>
#include <string.h>
extern UBYTE *_ProgramName;

#include "opts.h"

#define KNAME_SIZE    200
#define DRIVER_SIZE    32
#define VOLUME_SIZE   200
char kernel_name[KNAME_SIZE+1]  = "netbsd";
char driver_name[DRIVER_SIZE+1] = "scsi.device";
char volume_name[VOLUME_SIZE+1] = "bsd_root";
long device_unit;
long memory_limit;
long nosync_mask;
long options;

UBYTE *nosync_parse(UBYTE *p, long *resp)
{
	long v = 0;
	long m = 1;
	UBYTE c;

	for (;;) {
		c = *p;
		if (c >= '0' && c <= '7')
			v |= m << (c - '0');
		else if (c == ',')
			m <<= 8;
		else
			break;
		++p;
	}

	*resp = v;
	return p;
}

#define TEMPLATE "MULTIUSER/S,ASKROOT/S,MACHINE/K/N,RESERVE/S,MEMLIMIT/K/N," \
                 "TWOSEG/S,MANYSEG/S,FIRSTSEG/S,TEST/S,SYMBOLS/S,KDB/S," \
                 "AGA/S,NOSYNC/K,DRIVER/K,UNIT/K/N,VOLUME/K,FAST/S,KERNEL"

VOID get_opts(UBYTE *cmdline)
{
	static char templ[] = TEMPLATE;
	struct RDArgs *rda;
	LONG args[18];
	UBYTE *p;
	int i;

	cpu_id       = 0;
	memory_limit = 0;
	nosync_mask  = 0;
	options = 0;

	if (DOSBase->dl_lib.lib_Version >= 36) {
		bzero(args, sizeof(args));
		rda = ReadArgs(templ, args, NULL);
		if (!rda) {
			PrintFault(IoErr(),_ProgramName);
			exit(RETURN_FAIL);
		}
	
		if (args[0])  options |= BOOT_MULTIUSER;
		if (args[1])  options |= ASK_ROOT_DEVICE;
		if (args[2])  cpu_id = *((LONG *)args[2]) << 16;
		if (args[3])  options |= RESERVE_FOUR_MEG;
		if (args[4])  memory_limit = *((LONG *)args[4]) * 1024;
		if (args[5])  options |= TWO_SEGMENTS;
		if (args[6])  options |= MANY_SEGMENTS;
		if (args[7])  options |= USE_FIRST_SEGMENT;
		if (args[8])  options |= TEST_ONLY;
		if (args[9])  options |= INCLUDE_SYMBOLS;
		if (args[10]) options |= START_DEBUGGER;
		if (args[11]) options |= USE_AGA_DISPLAY;
		if (args[12]) (void)nosync_parse((char *)args[12], &nosync_mask);
		if (args[13]) strncpy(driver_name, (char *)args[13], DRIVER_SIZE);
		if (args[14]) device_unit = *(LONG *)args[14];
		if (args[15]) strncpy(volume_name, (char *)args[15], VOLUME_SIZE);
		if (args[16]) options |= FASTMEM_IMAGE;
		if (args[17]) strncpy(kernel_name, (char *)args[17], KNAME_SIZE);
	
		if (args[13] || args[14] || args[15])
			options |= KERNEL_FROM_ROOT;

		FreeArgs(rda);
	} else {
		/* 1.3 style */

		p = cmdline;

		i = 0;
		while (*p != '\0') {
			if (*p == '"')
				i = 1-i;
			else
				if (i == 0 && *p == ' ')
					break;
			++p;
		}

		while (*p == ' ' || *p == '\t')
			++p;

		while (*p != '\n' && *p != '\0') {
			switch (*p) {
			case '?':
				print("usage: gobsd [-abk123ptSDAF] "
				      "[=machine] [+memlimit] [%nosyncmask] "
				      "[~driver] [#unit] [ [:volume] [kernel]\n");
				exit(0);
			case ' ':
			case '\t':
				++p;
				break;
			case '-':   /* flags */
				++p;
				switch (*p) {
				case ' ':
				case '\t':
					--p;
					break;
				case 'a': options ^= BOOT_MULTIUSER; break;
				case 'b': options ^= ASK_ROOT_DEVICE; break;
				case 'k': options ^= RESERVE_FOUR_MEG; break;
				case '1': options ^= TWO_SEGMENTS; break;
				case '2': options ^= MANY_SEGMENTS; break;
				case '3': options ^= MANY_SEGMENTS | TWO_SEGMENTS; break;
				case 'p': options ^= USE_FIRST_SEGMENT; break;
				case 't': options ^= TEST_ONLY; break;
				case 'S': options ^= INCLUDE_SYMBOLS; break;
				case 'D': options ^= START_DEBUGGER; break;
				case 'A': options ^= USE_AGA_DISPLAY; break;
				case 'F': options ^= FASTMEM_IMAGE; break;
					break;
				default:
					print("unknown option ");
					printchar(*p);
					print("ignored\n",*p);
					break;
				}
				++p;
				break;
			case '=':   /* cpu type */
				++p;
				cpu_id = 0;
				while (*p >= '0' && *p <= '9') {
					cpu_id = cpu_id * 10 + (*p - '0');
					++p;
				}
				cpu_id <<= 16;
				break;
			case '+':   /* memory limit */
				memory_limit = 0;
				++p;
				while (*p >= '0' && *p <= '9') {
					memory_limit = memory_limit * 10 + (*p - '0');
					++p;
				}
				memory_limit *= 1024;
				break;
			case '%':
				p = nosync_parse(p+1, &nosync_mask);
				break;
			case '~':  /* driver name */
				for (i=0; i<DRIVER_SIZE; ++i) {
					if (*p == '\n' || *p == '\0')
						break;
					driver_name[i] = *p++;
				}
				driver_name[i] = '\0';
				options |= KERNEL_FROM_ROOT;
				break;
			case '#':   /* device unit */
				device_unit = 0;
				++p;
				while (*p >= '0' && *p <= '9') {
					device_unit = device_unit * 10 + (*p - '0');
					++p;
				}
				options |= KERNEL_FROM_ROOT;
				break;
			case ':':  /* volume name */
				for (i=0; i<VOLUME_SIZE; ++i) {
					if (*p == '\n' || *p == '\0')
						break;
					volume_name[i] = *p++;
				}
				volume_name[i] = '\0';
				options |= KERNEL_FROM_ROOT;
				break;
			default:    /* kernel name */
				for (i=0; i<KNAME_SIZE; ++i) {
					if (*p == '\n' || *p == '\0')
						break;
					kernel_name[i] = *p++;
				}
				kernel_name[i] = '\0';
				break;
			}
		}
	}
}
