#include <stdio.h>
#include <fcntl.h>
#include <ios1.h>
#include <string.h>
#include <stdlib.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <proto/exec.h>

#define MAXARG 256	/* maximum command line arguments */
#define QUOTE  '"'
#define ESCAPE '*'
#define ESC '\027'
#define NL '\n'

#define isspace(c) ((c == ' ')||(c == '\t') || (c == '\n'))

#ifndef TINY
extern int _fmode,_iomode;
extern int (*_ONBREAK)();
extern int CXBRK();
#endif

extern void main(int argc, char **argv);

extern char *_ProgramName;
extern struct UFB _ufbs[];
static int argc;		/* arg count */
static char *argv[MAXARG];	/* arg pointers */
static void badarg(char *program);

#define MAXWINDOW 40

/*
 * name		_xmain - process command line, open files, and call "main"
 *
 * synopsis	_xmain(line, length);
 *		char *line;	argument string to command
 *		int  length	length of argument string
 *
 * description	This function performs the standard pre-processing for
 *		the main module of a C program. It accepts a command
 *		line of the form
 *
 *			arg1 arg2 ...
 *
 *		and builds a list of pointers to each argument. The first
 *		pointer is to the program name. For some environments, the
 *		standard I/O files are also opened, using file names that
 *		were set up by the OS interface module XCMAIN.
 */

/*
 * This is a modified umain.c, supplied with the Lattice 5.04 compiler,
 *	that correctly handles AmigaDos escapes.
 *
 *					Ray
 */

void _xmain(char *line, int length)
	{
	char *argbuf;
	int x;

	/*
	 *
	 * Open standard files
	 *
	 */
#ifndef TINY

	_ufbs[0].ufbfh = Input();
	_ufbs[1].ufbfh = Output();
	_ufbs[2].ufbfh = Open("*", MODE_OLDFILE);

	_ufbs[0].ufbflg |= UFB_RA | O_RAW | UFB_NC;
	_ufbs[1].ufbflg |= UFB_WA | O_RAW | UFB_NC;
	_ufbs[2].ufbflg |= UFB_RA | O_RAW | UFB_WA;

	stdin->_file  = 0;
	stdout->_file = 1;
	stderr->_file = 2;

	x = (_fmode) ? 0 : _IOXLAT;
	stdin->_flag  = _IOREAD | x;
	stdout->_flag = _IOWRT  | x;
	stderr->_flag = _IORW   | x;

	/* establish control-c handler */

	_ONBREAK = CXBRK;

#endif

	if (!(argbuf = malloc(_ProgramName[-1] + length + 2)))
		{
		_exit(1);
		}

	argv[argc++] = argbuf;
	strncpy(argbuf, _ProgramName, _ProgramName[-1]);
	argbuf += _ProgramName[-1];
	*argbuf++ = '\0';

	/*
	 *
	 * Build argument pointer list
	 *
	 */
	while (argc < MAXARG)
		{
		while (isspace(*line) && length)
			{
			line++;
			length--;
			}
		if (!length)
			{
			break;
			}
		argv[argc++] = argbuf;
		if (*line == QUOTE)
			{
			line++;
			length--;
			while (length && (*line != QUOTE))
				{
				if (*line == ESCAPE)
					{
					line++;
					length--;
					if (!length)
						{
						badarg(*argv);
						}
					else
						{
						switch (*line)
							{
							case 'E':
								*argbuf++ = ESC;
								break;
							case 'N':
								*argbuf++ = NL;
								break;
							default:
								*argbuf++ = *line;
							}
						length--;
						line++;
						}
					}
				else
					{
					*argbuf++ = *line++;
					length--;
					}
				}

			if (!length)
				{
				badarg(*argv);
				}

			line++;
			length--;
			*argbuf++ = '\0';	/* terminate arg */

			if (length && !isspace(*line))
				{
				badarg(*argv);
				}
			}
		else  /* non-quoted arg */
			{
			while (length && (!isspace(*line)))
				{
				*argbuf++ = *line++;
				length--;
				}
			if (!length)
				{
				*argbuf = '\0';
				break;
				}
			else
				{
				*argbuf++ = '\0';	/* terminate arg */
				}
			}
		}  /* while */

	/*
	 *
	 * Call user's main program
	 *
	 */

	main(argc, argv);	/* call main function */
#ifndef TINY
	exit(0);
#else
	_exit(0);
#endif
	}


static void badarg(char *program)
	{
	fputs("Invalid argument to ", stderr);
	fputs(program, stderr);
	fputc('\n', stderr);
	exit(100);
	}
