/** Filelist.c
  *
  *   From Scott Ballantyne's demo
  *
  *
  *	Implement the File List functions for rexxarplib.library.
  *
  *   AUTHOR/DATE:  W.G.J. Langeveld, November 1987.
  *   ============
  *
  *	CURRENT VERSION:
  *
  *	This version has been converted to SAS C 6.5 format. It has been modified
  *	for modern definition sequences for ANSI compilation. This no longer works
  *	with OS versions prior to 2.04.
  *
  *	This module supports a major modification. All the large objects formerly
  * allocated on the stack are not allocated as a member of a local group of
  *	variables using mymalloc and myfree. This stops a stack crash which
  *	occured on machines running Picasso 96, and probably other RTG tools.
  *
  * Latest change is to fix so it compiles with 3.9 NDK.
  *
  *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, June 1998.
  *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, 23 Apr 2002.
  *   ============
  *
  **/

#include <functions.h>
#include "ralprotos.h"
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>					/* For ERROR_NO_MORE_ENTRIES, ^C, etc. */
#include <proto/rexxsyslib.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ctype.h>
#include "rexxarplib.h"
#include <libraries/MyARP.h>

extern struct ArpBase *ArpBase;
//extern struct DosLibrary *DOSBase; Not used

static char *ExpandPath(char *, char *);


struct UserAnchor 
{
	struct ARPAnchorPath ua_AP;
	BYTE moremem[255];						/* cheap way to extend ap_Buf[] */
};


char *rxf_filelist( long *err, int n, char **s )
{
	struct Rxfg3
	{
		char	rv[256],
				tmpbuf[256];
	} *rxfg = NULL;

	struct  UserAnchor *Anchor;
	long    error = 0L;
	char    *buf, *ptr,	bf[25];
	int     bl, num = 0, doit = 0;
	struct RexxMsg *rmptr = (struct RexxMsg *) s;
	
	rxfg = mymalloc( sizeof ( struct Rxfg3 ));
	if (rxfg == NULL)
		return( NULL );

	*err = 17L;
	if (n < 2 || n > 4)
		goto cleanup;
	
	*err = 10L;
	if (CheckRexxMsg( rmptr) == 0L)
		goto cleanup;
	
	*err = 3L;
	if ((Anchor = (struct UserAnchor *)
		ArpAlloc((long) sizeof(*Anchor)) ) == NULL) goto cleanup;
	
	Anchor->ua_AP.ap_StrLen = 255;
	/*
	 *   Get the first file
	 */
	*err = FindFirst(rmptr->rm_Args[1], (struct ARPAnchorPath *) Anchor);
	
	while (*err == 0L) 
	{
		buf = Anchor->ua_AP.ap_Buf;
		bl = strlen(buf);
		
		doit = 1;
		if (n >= 3) 
		{
			if (Anchor->ua_AP.ap_Info.fib_DirEntryType < 0) 
			{
				/*
				 *   Files
				 */
				if (rmptr->rm_Args[3]) 
				{
					if ((rmptr->rm_Args[3][0] | ' ') == 'd')
						doit = 0;
				}
			}
			else
			{
				/*
				 *   Directories
				 */
				if (rmptr->rm_Args[3]) 
				{
					if ((rmptr->rm_Args[3][0] | ' ') == 'f')
						doit = 0;
				}
			}
		}
		
		if (doit) 
		{
			num++;
			MakeStem( rxfg->rv, rmptr->rm_Args[2], num);
			if (n >= 4) 
			{
				if (rmptr->rm_Args[4]) 
				{
					if ((rmptr->rm_Args[4][0] | ' ') == 'e') 
					{
						buf = ExpandPath(buf, rxfg->tmpbuf);
					}
					else
					if ((rmptr->rm_Args[4][0] | ' ') == 'n') 
					{
						ptr = rindex(buf, '/');
						if (ptr == NULL)
							ptr = rindex(buf, ':');
						if (ptr)
							ptr++;
						else
							ptr = buf;
						buf = ptr;
					}
					bl = strlen(buf);
				}
			}
			error = SetRexxVar( rmptr, rxfg->rv, buf, (long) bl);
		}
		
		*err = FindNext( (struct ARPAnchorPath *) Anchor);
	}
	
	FreeAnchorChain((struct ARPAnchorPath *) Anchor);
	
	if      (error)
		*err = 12L;
	else
	if (*err == ERROR_OBJECT_NOT_FOUND)
		*err = 0L;
	else
	if (*err == ERROR_BUFFER_OVERFLOW )
		*err = 3L;
	else
	if (*err != ERROR_NO_MORE_ENTRIES )
		*err = 12L;
	else
		*err = 0L;
	/*
	 *   Make "stem.0" also have the number of files
	 */
	if (*err == 0L) 
	{
		ltoa(bf, (long) num);
		bl = strlen(bf);
		MakeStem( rxfg->rv, rmptr->rm_Args[2], 0);
		error = SetRexxVar( rmptr, rxfg->rv, bf, (long) bl);
	}
	
	cleanup:

	myfree( rxfg );

	if (num)
		return(CAS(bf));
	else
		return(CAS("0"));
}


/**
 *
 *   This function expands a filename to include the full pathname
 *
**/
static char *ExpandPath( char *fn, char *tmpbuf )
{
	BPTR lock;
	long len;
	
	tmpbuf[0] = '\0';
	
	lock = Lock(fn, ACCESS_READ);
	if (lock) 
	{
		len = PathName(lock, tmpbuf, 256L);
		UnLock(lock);
	}
	
	return(tmpbuf);
}


