
/* Generated by Interface Builder, modified by the author */

/* File: MethodTable.m */

#include <stdio.h>
#include <string.h>

#import "MethodTable.h"
#import "ClassTable.h"

#import <streams/streams.h>

#import <objc/Storage.h>

#import <appkit/Matrix.h>
#import <appkit/Text.h>

@implementation MethodTable

typedef struct _methodinfo
{
	char methodName[256];
} METHODINFO;

- init /* init object */
{
	[super init];
	
	table= [[Storage alloc] initCount:100 elementSize:sizeof( METHODINFO) description:NULL];
	numberOfElements= 0;
	
	return self;
}

- reset /* reset object */
{
	[table empty];
	numberOfElements= 0;
	
	return self;
}

- textlineToMethod:(char *)aTextline /* convert a textline to method */
{
	char *source, *source2, *dest;
	
	if( (source= index( aTextline, ';')) != NULL) /* only in interface files */
	{
		*source= (char)0;
	}
	
	source= dest= aTextline;
	while( *source != (char)0)
	{
		while( (*source != '/') && (*source != (char)0)) /* skip comments */
		{
			*dest++= *source++;
		}
		if( (*source == '/') && (*(source+1) == '*'))
		{
			source += 2;
			do
			{
				while( (*source != '*') && (*source != (char)0))
				{
					source++;
				}
				if( *source == '*')
				{
					source++;
				}
			}
			while( (*source != '/') && (*source != (char)0));
			if( *source == '/')
			{
				source++;
			}
		}
		else
		{
			*dest++= *source++;
		}
	}
	*dest= (char)0;
	
	source= dest= aTextline;
	*dest++= *source++; /* '-' or '+' */
	*dest++= *source++; /* one space */
	while( *source == ' ') /* not more */
	{
		source++;
	}
	if( *source == '(') /* typecast ? */
	{
		while( (*source != ')') && (*source != (char)0))
		{
			source++;
		}
		if( *source == ')')
		{
			source++;
		}
		while( *source == ' ')
		{
			source++;
		}
	}
	while( (*source != ' ') && (*source != ':') && (*source != (char)0)) /* method */
	{
		*dest++= *source++;
	}
	while( (*source != ':') && (*source != (char)0))
	{
		source++;
	}
	if( *source == ':')
	{
		*dest++= *source++;
	}
	while( *source != (char)0) /* parameter */
	{
		while( (*source != ':') && (*source != (char)0))
		{
			source++;
		}
		if( *(source2= source) == ':')
		{
			do
			{
				source--;
			}
			while( (*source != ' ') && (*source != ':') && (*source != ')'));
			if( *source == ' ')
			{
				source++;
				while( *source != ':')
				{
					*dest++= *source++;
				}
			}
			else
			{
				source= source2;
			}
			*dest++= *source++;
		}
	}
	*dest= (char)0;
	
	return self;
}

- (BOOL)getLine:(char *)aString from:(NXStream *)aStream maxLength:(int)aMaxLength /* get line */
{
	int character, length;
	BOOL eof= NO;
	
	length= 0;
	while( (length < aMaxLength) && (eof= ((character= NXGetc( aStream)) != EOF)) &&
		(filePosition++) && (character != 10))
	{
		*aString++= (char)character;
		length++;
		
	}
	
	*aString= (char)0;
	
	if( !eof && (length == aMaxLength)) /* line to long ? */
	{
		while( (eof= ((character= NXGetc( aStream)) != EOF)) && (filePosition++) && 
			(character != 10)) /* skip the rest */
			;
	}
		
	return( !eof);
}

- scanFile:(char *)aFilename mode:(char)selector /* scan a file */
{
	char textline[1024], *textpos;
	int position;
	BOOL eof;
	METHODINFO methodinfo;
	NXStream *stream;
	
	*superclass= (char)0;
	if( (stream= NXMapFile( aFilename, NX_READONLY)) != NULL)
	{
		do
		{
			eof= [self getLine:textline from:stream maxLength:1023];
			
			if( (*superclass == (char)0) && !strncmp( textline, "@interface ", 11))
			{
				if( (textpos= index( textline+11, ':')) != NULL)
				{
					while( *(++textpos) == ' ')
						;
					strcpy( superclass, textpos); /* the superclass */
					textpos= superclass + strlen( superclass);
					while( *(--textpos) == ' ')
						;
					*(textpos+1)= (char)0;
				}
				else
				{
					strcpy( superclass, "???"); /* no superclass */
				}
			}
			
			if( (textline[0] == selector) && (textline[1] == ' ')) /* new method ? */
			{
				[self textlineToMethod:textline];
				strcpy( methodinfo.methodName, textline);
				position= 0; /* search position to insert */
				while( (position < numberOfElements) && 
					(NXOrderStrings(
					(unsigned char *)((METHODINFO *)[table elementAt:position])->methodName,
					(unsigned char *)methodinfo.methodName, YES, -1, NULL) < 0))
				{
					position++;
				}
				[table insert:&methodinfo at:position]; /* insert */
				numberOfElements++;
			}
		}
		while( !eof);
		
		NXClose( stream);
	}
	
	return self;
}

- scanFile:(char *)aFilename lookAfter:(int)aMethod isInterface:(BOOL)flag start:(int *)start end:(int *)end /* scan a file */
{
	char filename[1024], textline[1024], *methodName;
	BOOL eof;
	NXStream *stream;
	
	filePosition= *end= 0;
	methodName= (char *)((METHODINFO *)[table elementAt:aMethod])->methodName;
	strcpy( filename, aFilename);
	if( !flag)
	{
		strcpy( rindex( filename, '.'), ".m");
	}
	
	if( (stream= NXMapFile( filename, NX_READONLY)) != NULL) /* open file */
	{
		do
		{
			*start= filePosition; /* start */
			eof= [self getLine:textline from:stream maxLength:1023];
			
			if( ((textline[0] == '-') || (textline[0] == '+')) && (textline[1] == ' '))
			{
				[self textlineToMethod:textline];
				if( eof= !strcmp( textline, methodName)) /* method found ? */
				{
					*end= filePosition; /* end */
				}
			}
		}
		while( !eof);
		
		NXClose( stream);
	}
	
	if( *end == 0) /* nothing found ? */
	{
		*start= 0;
	}
	
	return self;
}

- (int)fillMatrix:aMatrix /* fill a matrix */
{
	int count;
	
	for( count= 0; count < numberOfElements; count++)
	{
		[[aMatrix addRow] setTitle:((METHODINFO *)[table elementAt:count])->methodName
			at:count:0];
	}
	
	return numberOfElements;
}

- (BOOL)fillFile:(char *)aFilename
{
	char method[256];
	int count;
	BOOL ok;
	NXStream *stream;
	
	if( ok= ((stream= NXOpenMemory( NULL, 0, NX_WRITEONLY)) != NULL)) /* open stream */
	{
		for( count= 0; count < numberOfElements; count++)
		{
			strcpy( method, ((METHODINFO *)[table elementAt:count])->methodName);
			strcat( method, "\n");
			NXWrite( stream, method, strlen( method)); /* write method */
		}
		
		ok= (NXSaveToFile( stream, aFilename) == 0); /* save to file */
		NXCloseMemory( stream, NX_TRUNCATEBUFFER); /* close stream */
	}
	
	return ok;
}

- (char *)getSuperclass /* get the superclass */
{
	return superclass;
}

@end
