/* HaddColFuncton.m	by Paul Kunz	November 1992
 * Hippo function to add column to n-tuple
 *
 * Copyright (C)  1992  The Board of Trustees of
 * The Leland Stanford Junior University.  All Rights Reserved.
 */ 

#import "Draw.subproj/draw.h"
#import "HAddColFunction.h"


const char HAddColFunction_h_rcsid[] = HADDCOLFUNCTION_H_ID;
const char HAddColFunction_m_rcsid[] = "$Id: HAddColFunction.m,v 2.8.2.1 1994/01/05 02:21:58 rensing Exp $";

#import "HDrawApp.h"
#import "HTuple.h"
#import "InspectFunc.h"
#include <ctype.h>


/*
 * function to produce a valid (C) variable name from an arbitrary string
 */
static void makeVarName(char *);

@implementation HAddColFunction

- init
{
    [super init];
    colIndex = -1;	/* indicates not yet loaded */
    return self;
}

- initSource:(LANGUAGE)aLanguage for:(HTuple *)hTuple withName:(const char *)aName
{
    ntuple 		nt;
    char 		string[33];
    int                 i, count;

    [self init];
    language = aLanguage;
    name = NXCopyStringBufferFromZone( aName, [self zone] );
    codeStream = NXOpenMemory(NULL, 0, NX_READWRITE);
    initHTuple = hTuple;
    nt = [hTuple ntuple];
    switch (language) {
    case ANSI_C:
	NXPrintf(codeStream, "#include <math.h>\n" );
	NXPrintf(codeStream, "\n");
	if (nt) {
	     NXPrintf(codeStream, "struct ntRow {\n");
	     count = h_getNtDim(nt);
	     for (i = 0; i < count; i++) {
		  strncpy(string,h_getNtLabel(nt, i),32);
		  makeVarName(string);
		  NXPrintf(codeStream, "    float %s;\n", string);
	     }
	     NXPrintf(codeStream, "};\n\n");
	}
	NXPrintf(codeStream,
		 "float %s( int row, const struct ntRow *tuple )\n", name);
	NXPrintf(codeStream, "{\n\n");
	NXPrintf(codeStream, "    float returnValue;\n");
	NXPrintf(codeStream, "\n");
	NXPrintf(codeStream, "    return returnValue;\n");
	NXPrintf(codeStream, "}\n");
	break;
    case FORTRAN:
	NXPrintf(codeStream, "      Real*4 Function %s( rowValue )\n", name );
        NXPrintf(codeStream, "\n" );
	NXPrintf(codeStream, "      Real*4 rowValue(*)\n" );
        NXPrintf(codeStream, "\n" );
	if ( nt) {
	   count = h_getNtDim(nt);
	   for ( i = 0; i < count; i++ ) {
		strncpy(string,h_getNtLabel(nt, i),32);
		makeVarName(string);
		NXPrintf(codeStream, "      Real*4 %s\n", string);
		NXPrintf(codeStream, "      Equivalence(%s, rowValue(%d))\n",
			 string, i );
	   }
	   NXPrintf(codeStream, "\n");
        }
	NXPrintf(codeStream, "      Real*4 returnValue\n");
	NXPrintf(codeStream, "\n");
	NXPrintf(codeStream, "      %s = returnValue\n", name );
	NXPrintf(codeStream, "      return\n");
	NXPrintf(codeStream, "      end\n");
	break;
	
    default:
        break;
    }
    NXFlush(codeStream);
    return self;
}

/* Column related stuff from Qureshi
 * should be separted out in other class
 *Begin
- initColumnText:(int) aLanguage
{
    char string[33];
    int                 i, count;

    language = aLanguage;
    codeStream = NXOpenMemory(NULL, 0, NX_READWRITE);
    switch (language) {
    case ANSI_C:
	NXPrintf(codeStream, "#include <math.h>\n" );
	NXPrintf(codeStream, "\n");
	if (inputTuple) {
	     count = h_getNtDim(inputTuple);
	     for (i = 0; i < count; i++) {
		  strncpy(string,h_getNtLabel(inputTuple, i),32);
		  NXPrintf(codeStream, "#define \t%s \t %d\n", string,i+1);
	     }
	     NXPrintf(codeStream, "\n\n");
	}
	NXPrintf(codeStream,
		 "float %s(  float *column, int size, int columnNumber )\n", name);
	NXPrintf(codeStream, "{\n");
	NXPrintf(codeStream, "    float returnValue;\n\n");
	NXPrintf(codeStream, "\n");
	NXPrintf(codeStream, "    return returnValue;\n");
	NXPrintf(codeStream, "}\n");
	break;
    case FORTRAN:
	NXPrintf(codeStream, "      Real*4 Function %s( rowValue )\n", name );
        NXPrintf(codeStream, "\n" );
	NXPrintf(codeStream, "      Real*4 rowValue(*)\n" );
        NXPrintf(codeStream, "\n" );
	if ( inputTuple) {
	   count = h_getNtDim(inputTuple);
	   for ( i = 0; i < count; i++ ) {
		strncpy(string,h_getNtLabel(inputTuple, i),32);
		makeVarName(string);
		NXPrintf(codeStream, "      Real*4 %s\n", string);
		NXPrintf(codeStream, "      Equivalence(%s, rowValue(%d))\n",
			 string, i );
	   }
	   NXPrintf(codeStream, "\n");
        }
	NXPrintf(codeStream, "      Real*4 returnValue\n");
	NXPrintf(codeStream, "\n");
	NXPrintf(codeStream, "      %s = returnValue\n", name );
	NXPrintf(codeStream, "      return\n");
	NXPrintf(codeStream, "      end\n");
	break;
	
    }
    return self;
}
End */

- (HTuple *) hTuple
{
    return initHTuple;
}
- (int) colIndex
{
    return colIndex;
}
- replace:(HTuple *)oldTuple with:(HTuple *)newTuple
{
    initHTuple = newTuple;
    return self;
}

typedef float (*colFunc)(int,const float *);
	  
- (int) executeWith:(ntuple) nt
{
    int		i, count;
    float       *ntRow = NULL;
    float 	*col;
    int         rowSize;
    
    if (!function) {
        return (-1);
    }
    if ( colIndex < 0 ) {
        if ((colIndex = h_addColumn( nt )) < 0) return (-1);
    }
    if ( name ) h_setNtLabel( nt, colIndex, name );
    col = h_getNtColumn( nt, colIndex );
    count = h_getNtNdata(nt);
    for ( i = 0; i < count; i++ ) {
        ntRow = h_getNtData(nt, i, ntRow, &rowSize);
	*col++ = (*(colFunc)function)(i,ntRow);
    }

    free(ntRow);
    return 0;
}

- (int) runWith:(HTuple *)hTuple
{
    HDrawApp		*hippoDraw;
    InspectFunc		*inspector;
    int			irc;
    
    hippoDraw = NXGetNamedObject("HDrawInstance", NXApp);
    irc = [self saveToTmpFile];
    if ( irc != 0 ) return irc;
    inspector = [hippoDraw inspectFunc];
    irc = [inspector performFunction:self with:[hTuple ntuple]];
    return irc;
}
/* Something left over from Qureshi's column functions
 * can't possible be working since compiler is undefined
 * Begin:
- executeColumn
{
    int		i, count;
    float       *ntCol = NULL;
    float 		*array;
    int         colSize;
    
     
    colfunction = [compiler findSymbol:name];
    if (!colfunction) {
        return self;
    }
     count = h_getNtDim(inputTuple);
	 colSize = h_getNtNdata(inputTuple);
	 array = (float*)malloc((count+2)*(sizeof(float)));
	 for (i=0; i < count; i++) {
	 	ntCol = (float*)h_getNtColumn(inputTuple,i);
		array[i] = (*colfunction)(ntCol,colSize,i+1);
	}
    
	h_arrayFill(inputTuple, array );

    return self;
}
end */

static void makeVarName(char *var)
{
     if (*var == '\0') return;
     
     /* first character MUST be an letter */
     if (! isalpha(*var)) *var++ = 'a';
     
     while (*var != '\0')
     {
	  if (! isalnum(*var)) 
	  {
	       /* try to make the variable name somewhat unique */
	       switch (*var)
	       {
   	           case '!': *var = '1'; break;
   	           case '@': *var = '2'; break;
   	           case '#': *var = '3'; break;
   	           case '$': *var = '4'; break;
   	           case '%': *var = '5'; break;
   	           case '^': *var = 'U'; break;
   	           case '&': *var = '7'; break;
   	           case '*': *var = 'S'; break;
   	           case '(': *var = '_'; break;
   	           case ')': *var = '_'; break;
   	           case '-': *var = 'M'; break;
   	           case '+': *var = 'P'; break;
   	           case '=': *var = 'E'; break;
   	           default : *var = '_'; break;
	       }
	  }
	  var++;
     }
}
- write:(NXTypedStream *)ts
{
    [super write:ts];
    NXWriteObjectReference( ts, initHTuple );
    return self;
}

- read:(NXTypedStream *)ts
{
    [super read:ts];
    initHTuple = NXReadObject(ts);
    return self;
}
@end
