
/*************************************************************************
**
** mach.c
** Copyright (c) 1995,1996 Daniel Kahlin <tlr@stacken.kth.se>
**
******/

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <error.h>
#include <ctype.h>
#include <string.h>

#include "main.h"
#include "main_rev.h"
#include "mach.h"

/*** machine dependent stuff ***/



#ifdef	AMIGA_VERSION


#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/doshunks.h>
#include <proto/dos.h>
#include <proto/exec.h>



int	didrdargs=FALSE;
struct RDArgs *rdargs=NULL;
char *version={"$VER: "PROGRAM_SHORTNAME" "PROGRAM_VER" "COMPILE_DATE};
struct Process *myprocess=NULL;
BPTR	oldlock=NULL;
APTR	oldwindowptr=NULL;

int breakhandler(void);

/*************************************************************************
**
** mach_startup
**
******/
void mach_startup(void)
{
/* print title */
	if (IsInteractive(Output()))
		puts(BOLD PROGRAM_NAME " " PROGRAM_VER " " ITALICS "Copyright (c) 1995,1996 Daniel Kahlin." NORMAL);
	else
		puts(PROGRAM_NAME " " PROGRAM_VER "  Copyright (c) 1995,1996 Daniel Kahlin." );

/* set mach config defaults */
	o5config.serdevice="serial.device";
	o5config.serunitnum=0;

/* general init */
	if (onbreak(&breakhandler))
		panic("couldn't set break trap");
	if (!(rdargs=(struct RDArgs *)AllocDosObject(DOS_RDARGS,NULL)))
		panic("no mem");
	myprocess=(struct Process *)FindTask(NULL);
	/*oldlock=myprocess->pr_CurrentDir;*/
	oldwindowptr=myprocess->pr_WindowPtr;

}


/*************************************************************************
**
** mach_noerror
**
******/
void mach_noerror(void)
{
/* disable requesters */
	myprocess->pr_WindowPtr=(void *)-1;
}

/*************************************************************************
**
** NAME  mach_rdargs()
**
** SYNOPSIS
**   ret=mach_rdargs(thetemplate, array, params)
**   int mach_rdargs(char *, LONG *, char *)
**
** DESCRIPTION
**   parses the string params according to the template, and fills in
**   array.
**   the template consists of several entries separated by commas.
**   Every entry has a corresponding place in the array.
**   If a parameter is enclosed by quotes they will be stripped.
**   Abbreviations are allowed using "abbrev=option" (ex. "Q=QUICK")
**   The default option is String.
**
**   /S - Switch.  If present, array location will be non-zero.  Zero
**        otherwise.
**
**   /N - Number.  If present, array location will contain a pointer
**        to the longword.  Zero otherwise.
**
**   /A - Required. This option must be given a value, or an error is
**        given.
**
**   /M - Multiple strings. Will take any number of strings. array
**        location will contain a pointer to an array of strings.
**        If there are '/A' options after the '/M', they will be
**        filled from the end of the '/M' option.
**        Ex: Copy ("FROM/A/M,TO/A").  If you try COPY apa groda disk,
**        the first array location will contain a pointer to an array
**        with the strings 'apa' and 'groda'. The second array location
**        will contain a pointer to 'disk'.
**
** INPUTS
**   thetemplate- template describing how to parse.
**   array      - array to be filled.
**   params     - argument string to be parsed.
**
** RESULT
**   ret        - status TRUE is ok.
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_getargstr()
**
******/
int mach_rdargs(char *thetemplate, LONG *array,char *params)
{
	if (params) {
		rdargs->RDA_Source.CS_Buffer=params;
		rdargs->RDA_Source.CS_Length=strlen(params);
	} else {
		rdargs->RDA_Source.CS_Buffer="\n";
		rdargs->RDA_Source.CS_Length=1;
	}
	if (!(rdargs=ReadArgs(thetemplate,(LONG *)array,rdargs))) 
		panic("error in args");
	didrdargs=TRUE;
	return(TRUE);
}


/*************************************************************************
**
** mach_closeall
**
******/
void mach_closeall(int ret)
{
	if (myprocess) {
		/*CurrentDir(oldlock);*/
		myprocess->pr_WindowPtr=oldwindowptr;
	}
	if (didrdargs) FreeArgs(rdargs);
	if (rdargs) FreeDosObject(DOS_RDARGS, rdargs);
}

/*************************************************************************
**
** Handle break!
**
******/
int breakhandler(void)
{
	puts("***Brääk!");
	closeall(0);
	return(0);
}


/*************************************************************************
**
** NAME  mach_getargstr()
**
** SYNOPSIS
**   args=mach_getargstr()
**   char *mach_getargstr(void)
**
** DESCRIPTION
**   Returns a pointer to a string containing the arguments, excluding
**   the command itself.
**
** INPUTS
**   none
**
** RESULT
**   args       - pointer to a command line. 
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_rdargs()
**
******/
char *mach_getargstr(void)
{
	return(GetArgStr());
}


/*************************************************************************
**
** NAME  mach_parsepattern()
**
** SYNOPSIS
**   mms=mach_parsepattern(patternstr)
**   struct mach_matchstruct *mach_parsepattern(char *)
**
** DESCRIPTION
**   Allocates and parses an pattern for use with mach_matchpattern()
**   later on.  Remember to free using mach_unparsepattern().
**
**   On the Amiga these patterns apply:
**
**----cut from the AmigaDOS dos.library autodocs--------------------------
**
**   ?       Matches a single character
**   #       Matches the following expression 0 or more times
**   (ab|cd) Matches any one of the items separated by '|'-
**   ~       Negates the following expression.  It matches all strings
**           that do not match the expression (i.e ~(foo) matches all
**           strings that are not exactly "foo").
**   [abc]   Character class: matches any of the characters in the class.
**   a-z     Character range (only within character classes).
**   %       Matches 0 characters always (useful in "(foo|bar|%)").
**   *       Synonym for "#?", not available by default. Available as an
**           option that can be turned on.
**
**------------------------------------------------------------------------
**
** INPUTS
**   patternstr - the actual pattern to use for matching
**
** RESULT
**   mms        - pointer to a mach_matchstruct
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_unparsepattern(), mach_matchpattern()
**
******/
struct mach_matchstruct *mach_parsepattern(char *patternstr)
{
	struct mach_matchstruct	*mms=NULL;

	if (!(mms=(struct mach_matchstruct *)jalloc(sizeof(struct mach_matchstruct))))
		panic("no mem");

	switch (ParsePatternNoCase(patternstr,mms->parsedpattern,512)) {

/* there where wildcards */
		case 1:
			mms->iswild=TRUE;
			return(mms);

/* there where NO wildcards */
		case 0:
			mms->iswild=FALSE;
			return(mms);

/* there was an error */
		case -1:
		default:
			panic("error in mach_matchstruct");
	}

}

/*************************************************************************
**
** NAME  mach_unparsepattern()
**
** SYNOPSIS
**   mach_unparsepattern(mms)
**   void mach_unparsepattern(struct mach_matchstruct *)
**
** DESCRIPTION
**   frees up resources after using a mach_matchstruct (must be
**   previously allocated by mach_parsepattern())
**
** INPUTS
**   mms        - pointer to a mach_matchstruct
**
** RESULT
**   none
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_parsepattern(), mach_matchpattern()
**
******/
void mach_unparsepattern(struct mach_matchstruct *mms)
{
	jfree((char *)mms);
	return;
}


/*************************************************************************
**
** NAME  mach_matchpattern()
**
** SYNOPSIS
**   ret=mach_matchpattern(mms,str)
**   int mach_matchpattern(struct mach_matchstruct *mms, char *str)
**
** DESCRIPTION
**   match a pattern with a string, and return TRUE if it matches.
**   This function is not case sensitive!
**   Pattern must have been allocated using mach_parsepattern().
**
** INPUTS
**   mms        - pointer to a mach_matchstruct
**   str        - string to match.
**
** RESULT
**   ret        - TRUE if it's a match.  FALSE otherwise.
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_parsepattern(), mach_unparsepattern()
**
******/
int mach_matchpattern(struct mach_matchstruct *mms, char *str)
{
	int ret;
	ret=MatchPatternNoCase(mms->parsedpattern,str);
	return(ret);
}




/*************************************************************************
**
** NAME  mach_lockdir()
**
** SYNOPSIS
**   mdl=mach_lockdir(path)
**   struct mach_dirlock *mach_lockdir(char *)
**
** DESCRIPTION
**   Allocates a mach_dirlock for use with mach_examine(), remember to
**   free using mach_unlock().
**
** INPUTS
**   path       - path to be examined. "" means the current directory
**
** RESULT
**   mdl        - a pointer to a mach_dirlock 
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_unlockdir(), mach_examine()
**
******/
struct mach_dirlock *mach_lockdir(char *path)
{
	struct mach_dirlock	*mdl=NULL;

	if (!(mdl=(struct mach_dirlock *)jalloc(sizeof(struct mach_dirlock))))
		panic("no mem");

	if (!(mdl->lock=Lock(path,ACCESS_READ))) {
		jfree((char *)mdl);
		return(NULL);
	}

	if (!Examine(mdl->lock, &(mdl->fib))) {
		UnLock(mdl->lock);
		jfree((char *)mdl);
		return(NULL);
	}
	return(mdl);
}


/*************************************************************************
**
** NAME  mach_unlockdir()
**
** SYNOPSIS
**   mach_unlockdir(mdl)
**   void mach_unlockdir(struct mach_dirlock *)
**
** DESCRIPTION
**   frees up resources after using a mach_dirlock (must be previously
**   allocated by mach_lockdir())
**
** INPUTS
**   mdl        - a pointer to a mach_dirlock obtained by mach_lockdir()
**
** RESULT
**   none
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_lockdir(), mach_examine()
**
******/
void mach_unlockdir(struct mach_dirlock *mdl)
{
	UnLock(mdl->lock);
	jfree((char *)mdl);
	return;
}

/*************************************************************************
**
** NAME  mach_examine()
**
** SYNOPSIS
**   mde=mach_examine(mdl)
**   struct mach_direntry *mach_examine(struct mach_dirlock *)
**
** DESCRIPTION
**   examines the next entry of the directory locked by mach_lockdir()
**   if no more entries are found a NULL pointer is returned.
**
** INPUTS
**   mdl        - a pointer to a mach_dirlock obtained by mach_lockdir()
**
** RESULT
**   mde        - a pointer to a mach_direntry, or NULL
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_lockdir(), mach_unlockdir()
**
******/
struct mach_direntry *mach_examine(struct mach_dirlock *mdl)
{
	if (ExNext(mdl->lock, &(mdl->fib))) {
		mdl->direntry.size=mdl->fib.fib_Size;
		mdl->direntry.name=(char *)&(mdl->fib.fib_FileName);
		mdl->direntry.type=mdl->fib.fib_DirEntryType; 
		return(&(mdl->direntry));
	}
	return(NULL);
}



/*************************************************************************
**
** NAME  mach_getpath()
**
** SYNOPSIS
**   filename=mach_getpath(fileref,path,maxsize)
**   char *mach_getpath(char *, char *, int)
**
** DESCRIPTION
**   copies the pathpart of fileref to path, and returns a pointer to
**   the filename.
**
** INPUTS
**   fileref    - the complete path & filename to be splitted
**   path       - where the path is copied
**   maxsize    - total max size of the path buffer (including '\0')
**
** RESULT
**   filename   - pointer to where the filename starts in the
**                original string.
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_addpart()
**
******/
char *mach_getpath(char *fileref, char *path, int maxsize)
{
	char *name;
	int len;
	char tkn;
	int i;

	len=strlen(fileref);

	if (len==0)
		return(NULL);

	for (i=len-1; i>=0; i--) {
		tkn=fileref[i];
		if (tkn=='/' || tkn==':') break;
	}

	if (i>0) {
		if (i>=maxsize)
			panic("string to big in mach_getpath (%d)",i);

		name=&fileref[i+1];
		strncpy(path,fileref,i+1);
		path[i+1]=0;
		return(name);
	} else {
		name=&fileref[0];
		path[0]=0;
		return(name);
	}
}


/*************************************************************************
**
** NAME  mach_addpart()
**
** SYNOPSIS
**   mach_addpart(path,name,size)
**   void mach_addpart(char *, char *, int)
**
** DESCRIPTION
**   Appends the name to the path string, if nessecary inserts a '/'.
**
** INPUTS
**   path       - path string on which name is to be appended
**   name       - name string which is to be appended.
**   size       - total max size of the path buffer (including '\0')
**
** RESULT
**   none
**
** BUGS
**   none known
**
** SEE ALSO
**   mach_getpath()
**
******/
void mach_addpart(char *path, char *name, int size)
{
	char	tkn;



/*
** If string is not empty and ends with a
** character other that '/' or ':', append a '/'.
** 
*/
	if (strlen(path)) {
		tkn=path[strlen(path)-1];

		if (!(tkn=='/' || tkn==':'))
			strncat(path,"/",size);
	}

/*
** append name to path
*/
	strncat(path,name,size);
	return;
}


#endif



/*
** Table for the config reader!
*/
struct ConfigTable configtable[]={
	{"DEVICE",	CT_NUMBER, (ULONG *)&o5config.device},
#ifdef AMIGA_VERSION
	{"SERIALDEVICE",	CT_STRING, (ULONG *)&o5config.serdevice},
	{"SERIALUNIT",	CT_NUMBER, (ULONG *)&o5config.serunitnum},
#endif
	{NULL,NULL}
};


