/*
 *  procker.h from ObjectProDSP 0.2
 *  Copyright (C) 1994 1995, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
/*  procker.h   */
/*  Copyright 1990 Mountain Math Software  */
/*  All Rights Reserved                    */
#include "portable.h"
#include "errcode.h"

#include "hrdarth.h"
class DfNode ;
class ostream ;

class IterationBase {
	DfNode * TheNode;
	ErrCode ErrorState ;
	int32 InLeftOver ;
	int32 OutLeftOver ;
	int OutChannel ;
public:
	IterationBase();
	virtual ~IterationBase() ;
	void SetTheNode(DfNode * the_node);
	DfNode * GetTheNode() const { return TheNode; }
	virtual ostream& DecodeIndex(ostream& In) const ;
	virtual int LoopInitialization();
	virtual ErrCode LoopCleanUp(ErrCode err_in);
	ErrCode GetErrorState() const {return ErrorState; }
	void SetErrorState(ErrCode NewState);
	int32 GetInLeftOver() const {return InLeftOver;}
	void SetInLeftOver(int32 val) {InLeftOver = val;}
	int32 GetOutLeftOver() const {return OutLeftOver;}
	void SetOutLeftOver(int32 val) {OutLeftOver = val;}
	void SetOutputChannel(int chan) {OutChannel = chan;}
};

class WordIterationIn: virtual public IterationBase {
	const MachWord*& InPoint ;
	int& InCount ;
	int InSave ;
public:
	WordIterationIn(DfNode* the_node, MachWord*& in_point, int& in_count) ;
	const MachWord * GetInPoint() const {return InPoint;}
	int GetInCount() const {return InCount;}
	virtual ostream& DecodeIndex(ostream& In) const ;
	virtual int LoopInitialization();
	virtual ErrCode LoopCleanUp(ErrCode ErrIn);
};

class WordIterationOut: virtual public IterationBase {
	MachWord *& OutPoint ;
	int& OutCount ;
	int OutSave ;
public:
	WordIterationOut(DfNode * the_node, MachWord*& out_point,
		int& out_count) ;
	// WordIterationOut(DfNode * the_node, MachWord*& out_point) ;
	MachWord * GetOutPoint() const {return OutPoint;}
	int GetOutCount() const {return OutCount;}
	virtual ostream& DecodeIndex(ostream& In) const ;
	virtual int LoopInitialization();
	virtual ErrCode LoopCleanUp(ErrCode ErrIn);
};

class WordIteration: public WordIterationIn, public WordIterationOut {
public:
	WordIteration(DfNode * the_node, MachWord*& in_point, int& in_count,
		MachWord*& out_point, int& out_count) ;
	ostream& DecodeIndex(ostream& In) const ;
	int LoopInitialization();
	ErrCode LoopCleanUp(ErrCode ErrIn);
};

class CxSampleIteration {
	DfNode * TheNode ;
	int LoopInitialization() ;
	ErrCode LoopCleanUp(ErrCode ErrIn);
};

class BlockIteration {
	DfNode * TheNode ;
	int LoopInitialization() ;
	ErrCode LoopCleanUp(ErrCode ErrIn);
};

#define BEGIN_LOOP_BASE(LoopType,channel,InDeclare,InAccess,OutDeclare,OutAccess) \
	static LoopType * LoopControl = 0 ; \
	InDeclare ; \
	OutDeclare ; \
	SetExecCount(0); \
	if (!LoopControl) LoopControl = new LoopType(this InAccess OutAccess); \
	if (!LoopControl->LoopInitialization()) goto LoopExit ; \
	LoopControl->SetOutputChannel(channel); \
	for (;;) {

#define EXIT_LOOP(Code) {LoopControl->SetErrorState(Code); goto LoopExit;}

#define IN_DECLARE \
	const static MachWord * InPoint ; \
	static int InCount ;

#define OUT_DECLARE \
	static MachWord * OutPoint ; \
	static int OutCount ;

#define IN_ACCESS , InPoint , InCount

#define OUT_ACCESS , OutPoint , OutCount

#define OUT_DECLARE_NO_TEST \
	static MachWord * OutPoint 

#define NULL_DEFINE

#define BEGIN_LOOP_TEST_OUT(LoopType,channel) BEGIN_LOOP_BASE(LoopType, \
	IN_DECLARE, IN_ACCESS, OUT_DECLARE, OUT_ACCESS)

#define BEGIN_INPUT_LOOP(LoopType) BEGIN_LOOP_BASE(LoopType, \
	IN_DECLARE, IN_ACCESS, NULL_DEFINE, NULL_DEFINE)

#define BEGIN_OUTPUT_LOOP(LoopType, channel) BEGIN_LOOP_BASE(LoopType, \
	channel, NULL_DEFINE, NULL_DEFINE, OUT_DECLARE, OUT_ACCESS)

#define BEGIN_LOOP(LoopType) BEGIN_LOOP_BASE(LoopType, \
	IN_DECLARE, IN_ACCESS, OUT_DECLARE_NO_TEST, OUT_ACCESS)


#define NEXT_IN(Input) { if (! InCount--) goto LoopExit ; \
	Input = *InPoint++ ;}

#define NEXT_OUT_TEST(Output) { *OutPoint++ = Output ; \
	if (! --OutCount) goto LoopExit ;}

#define NEXT_OUT(Output) *OutPoint++ = Output ;

#define END_LOOP(err) \
	} \
LoopExit: \
	err = LoopControl->LoopCleanUp(err)

