
//---------------------------------------------------------------------------
//   Sample AP for APLX
//---------------------------------------------------------------------------

// *** CAUTION: MAKE SURE YOU DEFINE LITTLE_ENDIAN IF COMPILING FOR WINDOWS OR OTHER
// ***          x86 PLATFORM.  THIS MUST BE DONE BEFORE INCLUDING aplx.h
//
// For Linux, compile with:
//
//		gcc -o ap103 -shared -I../unisup/include sample_ap.c
//
// This should create an output file 'ap103'.  Place this in the shared library
// path (eg in /usr/lib, or in a directory specified in the user's LD_LIBRARY
// environment variable).
//
// Then test in APL with:
//
//		103 []SVO 'DATA'
// 2								<-- If it doesn't return 2, processor not found
//
//      DATA <- []A					Give it a character vector
//
//      []AF DATA                   See what it returns
// 27
//
//
#define LITTLE_ENDIAN	1

#include "aplx.h"


int processor (
		int			op,				/* Operation code AP_xxx */
		WS_Entry	*data,			/* Pointer to APL data specified, or where to put result */
		int			wsfree,			/* Free workspace (in bytes) on AP referenced */
		void		*scratch,		/* Pointer to 256-byte scratch area for use by the AP */
		void		*wsbase,		/* Pointer to base of workspace */
		WS_Entry	*last_var,		/* On reference, pointer to header of last variable
									   specified, or NULL if last data was a constant */
		int			tie,			/* An internal tie number uniquely identifying shared var */
		ExportedProcs *exports)		/* Structure containting exported routines you can call */
{
	int		result;			/* Error code to return to APL */
	char	xor = '\0';		/* The XOR result */
	int		i;				/* Counter */

	switch (op) {
	
		case AP_LOADED:
			result = APL_GOOD;	/* Nothing to do */
			break;
			
		case AP_UNLOADED:
			result = APL_GOOD;	/* Nothing to do */
			break;
			
		case AP_SPECIFIED:
			if (data->we_type_rank == CHR_VEC) {
				for (i = 0; i < data->we_vec_length; i++)
					xor ^= data->we_vec_cdata[i];
				((char *)scratch)[0] = xor;			/* Save result */
				result = APL_GOOD;
			} else {
				result = APL_DOMERR;
			}
			break;
			
		case AP_REFERENCED:
			if (wsfree < 20) 
				return APL_WSFULL;
			data->we_reserved = 0;			/* Plug 0 in reserved field */
			data->we_len = 16;				/* total length of result */
			data->we_type_rank = CHR_SCL;	/* type and rank  of result */
			data->we_scl_cdata = ((char *)scratch)[0];/* return saved result */
			result = APL_GOOD;
			break;
	}
	return result;
}
