$(@ITERATE@$(@lock@CMD@$(@OUTFILE@$(CMD).c@/******************************************************************************
$(@HIDE@$(@outfile@@generating C source for $(CMD)
))
    MODULE
	$(CMD).c

    DESCRIPTION
$(DESCRIPTION)

    NOTES
	Kickstart 2.0+ required
	compiles w/ SAS/C v6.51

	'C' Source automatically generated from $(CMD).data

    BUGS
$(@IF@$(?BUGS)@$(BUGS))

    EXAMPLES
$(@IF@$(?EXAMPLES)@$(EXAMPLES))

    HISTORY
$(@IF@$(?HISTORY)@$(HISTORY))

    AUTHOR
	Bernd Noll, Brunnenstrasse 55, D-67661 Kaiserslautern
	b_noll@informatik.uni-kl.de

******************************************************************************/

/**************************************
	    Includes
**************************************/

#ifndef   EXEC_LIBRARIES_H
# include <exec/libraries.h>
#endif /* EXEC_LIBRARIES_H */

#ifndef   EXEC_MEMORY_H
# include <exec/memory.h>
#endif /* EXEC_MEMORY_H */

#ifndef   CLIB_EXEC_PROTOS_H
# include <clib/exec_protos.h>
#endif /* CLIB_EXEC_PROTOS_H */

#ifndef   DOS_DOS_H
# include <dos/dos.h>
#endif /* DOS_DOS_H */

#ifndef   DOS_DOSASL_H
# include <dos/dosasl.h>
#endif /* DOS_DOSASL_H */

#ifndef   CLIB_DOS_PROTOS_H
# include <clib/dos_protos.h>
#endif /* CLIB_DOS_PROTOS_H */

#include <proto/dos.h>
#include <proto/exec.h>
$(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
#include <proto/$(@TOLOWER@$(__name)).h>)))

$(@IF@$(?INCLUDES)@$(@WITH@INCLUDES@$(@ITERATE@
#include $(__value))))

/**************************************
	 Defines & Structures
**************************************/

#if !defined( WILDCARDFLAG ) /* <----------- Test for predefinition */
# define WILDCARDFLAG	"/W"
#endif

#if !defined( FORMATPREFIX ) /* <----------- Test for predefinition */
# define FORMATPREFIX	"\0$ARG: "
# define FORMATOFFSET	7
#elif !defined( FORMATOFFSET )
# define FORMATOFFSET	sizeof(FORMATPREFIX "")-1
#endif

#define STDIN  "STDIN"

#define VERSIONPREFIX	"\0$VER: "
#define VERSIONOFFSET	0

/* ---- We set the #ifdef around, since another    */
/*	architecture might support another address */
#ifndef   ABSEXECBASE
#define   ABSEXECBASE ((struct ExecBase **)4L)
#endif

#define MAXLINELEN  256
#define MAXPATHLEN  256 /* BCPL won't allow bigger strings */
#define EOF	    -1	/* 'C' convention */
#define ZERO	     0L /* NULL for BPTRs */

#if defined( PATTERNMATCHING )
# define WILDCARDADD	WILDCARDFLAG
#else
# define WILDCARDADD
#endif

#define BUFFERSIZE     MAXLINELEN
$(@IF@$(?BUFFERS)@
#ifndef STATIC_BUFFERS
#undef	BUFFERSIZE
#define BUFFERSIZE     *argv->bufsize
#endif)

struct _gvars {
    struct DosLibrary *_DOSBase;
    struct ExecBase   *_SysBase;
$(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
    //struct Library *_$(__name)Base;)))
    struct {
/* *************************** BEGIN USER FORMAT *************************** */
/* "$(@IF@$(?TEMPLATE)@$(TEMPLATE),)"              /* CLI FORMAT */
							/* ****** STRUCTURES */
$(@IF@$(?ARGUMENTS)@$(ARGUMENTS))$(@IF@$(?ARGS)@$(ARGS))

/* **************************** END USER FORMAT **************************** */
$(@IF@$(?Filter)@
	STRPTR *file;
	STRPTR	to;
)$(@IF@$(?BUFFERS)@        ULONG *bufsize;)
	int dummy; // Just to make sure this structure is not empty
    } _argv;
    //struct ExecBase	*_SysBase;
    //struct DosLibrary *_DOSBase;
$(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
    struct Library *_$(__name)Base;)))
$(@IF@$(?Filter)@
    BPTR    output;
    BPTR    input;
    int     infnum;
    STRPTR  inname;)
    ULONG   breakflag;
#   if defined( PATTERNMATCHING )
	struct AnchorPath *ap;
	UBYTE  _ap[sizeof(struct AnchorPath) + MAXPATHLEN + 4];
	ULONG	ap__ap_error;
#   endif
    struct {
/* *************************** BEGIN USER FIELD **************************** */
							/* ****** STRUCTURES */
$(@IF@$(?USERDATA)@$(USERDATA))
$(@IF@$(?BUFFERS)@
#ifndef STATIC_BUFFERS $(@WITH@BUFFERS@$(@ITERATE@
	STRPTR $(__name);))
#else $(@WITH@BUFFERS@$(@ITERATE@
	UBYTE $(__name) [BUFFERSIZE];))
#endif)

/* **************************** END USER FIELD ***************************** */
	int ____dummy;
    } _userdata;
}; /* struct _gvars */

#define SysBase     gvars->_SysBase
#define DOSBase     gvars->_DOSBase
$(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
#define $(__name)Base gvars->_$(__name)Base)))

#define outfile     gvars->output
#define infile	    gvars->input
#define argv	    (&gvars->_argv)
#define userdata    (&gvars->_userdata)

#define BREAKCHECK() (gvars->breakflag |= CheckSignal(SIGBREAKF_CTRL_C))
#define IS_BROKEN()  (gvars->breakflag)

/**************************************
	    Implementation
**************************************/


/* ---- we need that stub if compiling w/o __inline, since our */
/*	commands start w/ the first instruction of this module */
/*	if we compile w/ inlining, the function disappears     */

static __inline long _start(void) {
    long _main(void);
    return _main();
} /* _start */


$(@IF@$(?APPEND)||$(?ADDES)@
/* *************************** BEGIN USER ADDES **************************** */

$(@IF@$(?APPEND)@$(APPEND))
$(@IF@$(?ADDES)@$(ADDES))

#define SysBase     gvars->_SysBase
#define DOSBase     gvars->_DOSBase
/* **************************** END USER ADDES **************************** */)

$(@IF@$(?INIT)@
/* ---- Do allocations etc. */
static __inline long $(CMD)Init (struct _gvars *gvars) {
    long retval = 0;
/* **************************** BEGIN USER INIT **************************** */

$(INIT)

/* ***************************** END USER INIT ***************************** */
    return retval;
} /* $(CMD)Init */
)

/* ---- main function called for each input file */
static __inline long $(CMD)Fnc (struct _gvars *gvars) {
    long retval = 0;$(@IF@$(?BODY)@
/* **************************** BEGIN USER BODY **************************** */

$(BODY)

/* ***************************** END USER BODY ***************************** */)
    return retval;
} /* $(CMD)Fnc */

$(@IF@$(?EXIT)@
/* ---- Do Disposes etc. */
static __inline void $(CMD)Exit (struct _gvars *gvars) {
    /* long retval = 0; */
/* **************************** BEGIN USER EXIT **************************** */

$(EXIT)

/* ***************************** END USER EXIT ***************************** */
    /* return retval; */
} /* $(CMD)Exit */
)

$(@If@$(?Filter)@
/* ---- Select the First/next input file */
static __inline BPTR _nextfile (struct _gvars *gvars, ULONG final) {
    if (!argv->file) {
	if (!infile)
	    infile = Input();
	else
	    return FALSE;
	gvars->inname = STDIN;
    } else {
	if (infile)
	    Close(infile);

	if (final)
	    return FALSE;

	if (gvars->breakflag || CheckSignal(SIGBREAKF_CTRL_C)) {
	    SetIoErr(ERROR_BREAK);
	    return FALSE;
	}

#if !defined( PATTERNMATCHING )

	do {
	    STRPTR fn;
	    fn = gvars->inname = argv->file[gvars->infnum++];
	    if (!fn)
		return FALSE;

	    infile = Open(fn, MODE_OLDFILE);
	    PrintFault(IoErr(), fn);
	} while (!infile);
#else
#warn "the current PATTERNMATCHING implementation is very big (+120 byte)"

	if (!infile) {
	    gvars->ap		     = (void *)(((ULONG)gvars->_ap + 3) & ~3);
	    gvars->ap->ap_Strlen     = MAXPATHLEN;
	    gvars->inname	     = gvars->ap->ap_Buf;
	    /*
	    gvars->ap->ap_BreakBits  = 0;
	    gvars->ap->ap_FoundBreak = 0;
	    gvars->ap__ap_error      = 0;
	    */
	    goto has_to_open_new_slot;
	} /* if */

#define HAS_TO_OPEN_NEW_SLOT (gvars->ap__ap_error == ERROR_NO_MORE_ENTRIES)
	infile = ZERO;
	do {
	    STRPTR fn;
	    if (HAS_TO_OPEN_NEW_SLOT) {
		//if (gvars->ap__ap_error == ERROR_NO_MORE_ENTRIES)
		    MatchEnd(gvars->ap);

has_to_open_new_slot:
		if (!(fn = argv->file[gvars->infnum++]))
		    return 0;

		gvars->ap->ap_Flags = 0;
		gvars->ap__ap_error = MatchFirst(fn, gvars->ap);
	    } else {
		gvars->ap__ap_error = MatchNext(gvars->ap);
	    } /* if */

	    if (!gvars->ap__ap_error)
		infile = Open(fn = gvars->inname, MODE_OLDFILE);
	    if (gvars->ap__ap_error != ERROR_NO_MORE_ENTRIES)
		PrintFault(IoErr(), fn);
	} while (!infile);

#endif
    } /* if */
    return infile;
} /* _nextfile */
)

long _main (void)
{
    const char* version =
	       VERSIONPREFIX "$(CMD) $(VERSION) " __AMIGADATE__ + VERSIONOFFSET;
    long retval = 20;

#ifdef STACK_VARS
    struct _gvars _gvars  = { 0 };
# ifdef FIX_SASPP
    struct _gvars *gvars = (&_gvars);
# else
#   define gvars (&_gvars)
# endif

    SysBase = *((struct ExecBase**)ABSEXECBASE);
#else
    //struct _gvars *gvars = (struct _gvars *)(-(LONG)sizeof(argv));
    struct _gvars *gvars = NULL;

# if defined( FIX_SASOPT ) && defined( __USE_SYSBASE )
#  undef SysBase
    struct ExecBase *SysBase = *((struct ExecBase**)ABSEXECBASE);
    //if ((ULONG)&SysBase == ABSEXECBASE)
# endif
    if (gvars = AllocVec(sizeof (*gvars), MEMF_CLEAR)) {
	gvars->_SysBase = *((struct ExecBase**)ABSEXECBASE);
#endif

	if (DOSBase = (struct DosLibrary *)OpenLibrary (DOSNAME, 37)) {
	    struct RDArgs *args;
$(@IF@$(?BUFFERS)@#ifndef STATIC_BUFFERS
	    ULONG bufsize = MAXLINELEN;
	    argv->bufsize = &bufsize;
#endif)

$(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
	    if (!($(__name)Base = OpenLibrary("$(@TOLOWER@$(__name)).library",37)))
		goto closelibs;)))

	    retval   = 10;
	    if (args = ReadArgs(FORMATPREFIX
				"$(@IF@$(?TEMPLATE)@$(TEMPLATE)$(@If@$(?Filter)@,))"
$(@If@$(?Filter)@
				"FILE/M" WILDCARDADD
				",TO/K"
)$(@IF@$(?BUFFERS)@#ifndef STATIC_BUFFERS
				",BUFFERSIZE/N/K"
#endif
)				+ FORMATOFFSET,
			       (LONG*)argv, NULL)) {
$(@IF@$(?BUFFERS)@#ifndef STATIC_BUFFERS
		bufsize = *argv->bufsize;$(@WITH@BUFFERS@$(@ITERATE@
		if (!(userdata->$(__name) = AllocVec(bufsize, MEMF_CLEAR)))
		    goto freebuffers;))
#endif)

$(@If@$(?Filter)@
		outfile = argv->to ? Open(argv->to, MODE_NEWFILE) : Output();
		if (outfile) {)
		    $(@if@!$(?INIT)@retval = 0;)$(@if@$(?INIT)@if (!(retval = $(CMD)Init(gvars))) {)$(@If@$(?Filter)@
			while (_nextfile(gvars, retval)))
			    retval = $(CMD)Fnc (gvars);
			$(@if@$(?EXIT)@$(CMD)Exit(gvars);)
		    $(@if@$(?INIT)@} /* if */)
$(@If@$(?Filter)@
		    if (argv->to)
			Close(outfile);
		} /* if */)

freebuffers:
$(@IF@$(?BUFFERS)@#ifndef STATIC_BUFFERS$(@WITH@BUFFERS@$(@ITERATE@
		if (userdata->$(__name))
		    FreeVec(userdata->$(__name));))
#endif)

		FreeArgs (args);
	    } /* if */
	    if (retval)
		PrintFault(IoErr(), "$(CMD)");


closelibs: $(@IF@$(?LIBRARIES)@$(@WITH@LIBRARIES@$(@ITERATE@
	    if ($(__name)Base)
		CloseLibrary($(__name)Base);)))
	    CloseLibrary ((struct Library *)DOSBase);
	} /* if */
#ifndef STACK_VARS
	FreeVec (gvars);
    } /* if */
#endif
    return retval;
} /* _main */

/******************************************************************************
*****  END $(CMD).c
******************************************************************************/)))
