//
//  TAMSCharEngine.m
//  TamsAnalyzer
//
//  Created by matthew on Sun Nov 17 2002.
//  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
//
#define MWCHAR unichar
#define SCANSTRING 0
#define SCANTAG 1
#import "TAMSCharEngine.h"
#include "tams.h"
#include <string.h>
#include "newline.h"
#include <ctype.h>
#import "MyDocument.h"
#import "myResults.h"
#import "tamsutils.h"
#import "utils.h"
#import "MWFakeFile.h"
#import "MGWScanner.h"
//#import "ctQChar.h"

/* for ctlimitfunc */
#import "ctLimitFunc.h"
#import "ctLimitCrit.h"
//#import "ctReadChar.h"
//#import "ctUnlimitedRuns.h"
#import "coderec.h"
#import "myResults.h"
#import "prefBoss.h"

#define PRINTCODER(X, Y) {if([gPrefBoss showCoder] && [(NSString *)Y length]){[X appendString:@" ["]; [X appendString: Y]; [X appendString: @"]"];}}



@implementation TAMSCharEngine
/*
    These are the readchar functions
*/
-(id) init
{
    [super init];
    gTheData = nil;
    newlinecnt = 0L;
    dsLen = 0;
    searchEnum = 0;
    gFileSearchList = [[NSMutableArray alloc] init];
    ctLimitVault = nil;
    ctZoneVault = nil;
    ctLimString = nil;
    eofFlag = NO;
    cln = 0;
    noParFlag = 1;
    currScan = nil;
    scanMode = SCANSTRING;
    scanEndFlag = NO;
    scanVeryEndFlag = NO;
    allowTabFlag = 0;
    clnMode = YES;	
    hasLineNumbers = NO;
    escFlag = -1; //means not externally set

    ctRunVault = [[NSMutableArray alloc] init];
    tagVault = [[NSMutableArray alloc] init];
    clnBuff = [[NSMutableString alloc] init];
    
    ctLimitVault = [[NSMutableArray alloc] init];
   //[ctLimitVault retain];
    ctLimString = [[NSMutableString alloc] init];
    ctZoneVault = [[NSMutableArray alloc] init];
    if([gPrefBoss macNLValue] == 1)
        setnewline(MACNL);
    else
        setnewline(UNIXNL);
    inLimFlag = 0;


    return self;
}
-(id) initWithFile: (id) who
{
    [self init];
    [self addFileToSearchList: who];
    return self;
}
-(id) initWithString: (id) who
{
    MWFakeFile *ff;
    ff = [[[MWFakeFile alloc] initWithString: who] autorelease];
    return [self initWithFile: ff];
}

-(id) initWithFileAndStart: (id) who
{
    [self init];
    [self addFileToSearchList: who];
    [self startSearch];
    return self;
}
-(id) initWithStringAndStart: (id) who
{
    MWFakeFile *ff;
    ff = [[[MWFakeFile alloc] initWithString: who] autorelease];
    return [self initWithFileAndStart: ff];
}

-(id) initWithArrayAndStart: (id) who
{
    [self init];
    [self addArrayToSearchList: who];
    [self startSearch];
    return self;
}


-(void) dealloc
{
    if(currScan != nil) [currScan release];
    [gFileSearchList release];
    [ctRunVault release];
    [ctLimitVault release];
    [ctZoneVault release];
    [ctLimString release];
    [tagVault release];
    [clnBuff release];
    if(gTheData) [gTheData release];
    [super dealloc];
}

-(void) setGTheData: (NSString *) dd {if(gTheData) [gTheData release]; gTheData = dd; [dd retain];}


- (long)getnewlinecnt
{return newlinecnt;}

-(void) setnewlinecnt:(long) n
{newlinecnt = n;}

-(void) incnewlinecnt
{newlinecnt++;}
-(void) setNoPar:(int) value {noParFlag = value;}
-(int) nopar{return noParFlag;}
-(int) allowtab
{ 
    if(gCurrentTAMS) return [gCurrentTAMS global: @"tabflag"];
    else return allowTabFlag;
}

-(void) setAllowTab: (int) value
{allowTabFlag = value;}

-(int) isquoteok{
    if (gCurrentTAMS)
	return [gCurrentTAMS global: @"quoteflag"];
    else return 1;

}

-(void) initSearchListSystem
{
    dsLen = 0;
    searchEnum = 0;
    if(!gFileSearchList) gFileSearchList = [[NSMutableArray alloc] init];
}

-(void) addFileToSearchList: (MWFile *)who
{
    [gFileSearchList addObject: who];
}

-(void) addArrayToSearchList: (NSArray *)who
{
    [gFileSearchList addObjectsFromArray: who];
}

-(NSArray *)hotFileList
{
    return gFileSearchList;
}

-(void)setGCurrentDataSource: (id) theSource;
{
    gCurrentDataSource = theSource;
}
-(id) gCurrentDataSource
{
    return gCurrentDataSource;
}
-(void) setCharLocation: (int) loc
{
    dsLen = loc;
#ifdef SCANCODE
    if(currScan) [currScan setScanLocation: loc];
#endif
}

-(int) getCharLocation
{
    return dsLen;
}

-(void) clearSearchList
{
    [gFileSearchList removeAllObjects];
    if(searchEnum) [searchEnum release];
    searchEnum = nil;
    dsLen = 0;

}

-(void) startSearch
{
    MWFile *oldDoc;
    dsLen = 0;
    if(searchEnum) [searchEnum release];
    searchEnum = [gFileSearchList objectEnumerator];
    [searchEnum retain];
    oldDoc = hotSearchDocument;
    if(hotSearchDocument = [searchEnum nextObject])
    {
        [self setGTheData: [hotSearchDocument string]];
#ifdef SCANCODE
        if(currScan != nil)
            [currScan release];
        
        currScan = [[NSScanner alloc] initWithString: [self gTheData]];
        [currScan  setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString: @""]];
#endif
	//[self setGTheData: [hotSearchDocument getData]];
    }
    else
    {
#ifdef SCANCODE
        if(currScan) [currScan release];
        scanVeryEndFlag = YES;
#endif
	if(gTheData) [gTheData release];
	gTheData = nil;
        hotSearchDocument = oldDoc;
    }

}

-(NSString *) gTheData
{return gTheData;}

-(MWFile *) hotSearchDocument
{return hotSearchDocument;}

-(void) setEOF: (BOOL) what
{
    eofFlag  = what;
}
-(BOOL) getEOF
{
    return eofFlag;
}
-(void) resetDataStream
{
    dsLen = 0;
    [self setEOF: NO];
}
         
        
     
    
    

-(MWCHAR) getNextChar
{
    unsigned localtest;
    MWCHAR c;
    id oldDoc;
    
    if(!gTheData) {[self setEOF: YES]; return EOF;}
    localtest = dsLen;
    dsLen++;
    
       if(dsLen > [gTheData length])
       {
	    oldDoc = hotSearchDocument;
	    if(hotSearchDocument = [searchEnum nextObject])
	    {
                MWFile* tempSearchDocument = hotSearchDocument;
                hotSearchDocument = oldDoc;
		//need to implement message with the oldDoc
                if([gTheData length] > 0)
                    [self setCharLocation: [gTheData length] - 1];
                else
                    [self setCharLocation: 0];
		[[NSNotificationCenter defaultCenter] postNotificationName:@"TAMSFileHasEnded" object: oldDoc]; 
                hotSearchDocument = tempSearchDocument;
		[self setGTheData: [hotSearchDocument string]];
		dsLen = 0;
                if([gTheData length])
                    c = [gTheData characterAtIndex: dsLen ];
                else
                {
                    dsLen++;
                    return [self getNextChar];
                }
		dsLen++;
                clnMode = YES;
		return c;

	    }
	    else
	    {
		//[[NSNotificationCenter defaultCenter]
		//	    postNotificationName:@"TAMSFileHasEnded" object: oldDoc]; 
                hotSearchDocument = oldDoc;
                [self setEOF: YES];
		return EOF;
	    }
	} 
    return [gTheData characterAtIndex: dsLen - 1];
}
-(BOOL) hasLineNumbers {return hasLineNumbers;}
-(void) setEscFlag: (BOOL) value
{
    escFlag = value;
}

-(BOOL) readEscape
{

    if(escFlag == -1)
    {
        if(gCurrentTAMS) return [gCurrentTAMS global: @"escapeflag"];
        else return [gPrefBoss escapeBracesValue];
    }
    else
        return escFlag;
}
#define CLOSEBRACEERR [NSString stringWithFormat: @"Probable missing close brace in tag, file: %@", [[self hotSearchDocument] name]]
#ifdef SCANCODE
-(void) handleFileEnd
{
    id ds;
    NSString *sss;
    if ([currScan isAtEnd])
    {
#ifndef SCANCODE
        [[NSNotificationCenter defaultCenter] postNotificationName:@"TAMSFileHasEnded" object: hotSearchDocument]; 
#endif
        ds = hotSearchDocument;
        hotSearchDocument = [searchEnum nextObject];
        if(hotSearchDocument != nil)
        {
            newlinecnt = 0L;
    
            deadDataSource = ds;
            scanMode = SCANSTRING;
            [self setCharLocation: 0];
           scanEndFlag = YES;
            scanVeryEndFlag = NO;
            if(currScan != nil) [currScan release];
            sss = [hotSearchDocument string];
            [self setGTheData: sss];
            currScan = [[NSScanner alloc] initWithString: sss];
            [currScan setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString: @""]];

        }
        else
        {
            deadDataSource = ds;
            hotSearchDocument = ds;
            scanEndFlag = YES;
            scanVeryEndFlag = YES;
            //if(currScan != nil) [currScan release];
            //currScan = nil;
        }
    }
}

-(void) addNewLineCnt: (unsigned) amt
{
    newlinecnt += amt;
}
-(void) setLoc
{
    [self setCharLocation: [currScan scanLocation]];
}
-(int) scanNextChar: (MWCHAR *) c
{
    unsigned loc;
    if([currScan isAtEnd] == YES)
    {
        return ENDOFFILE;
    }
    loc = [currScan scanLocation];
    *c = [gTheData characterAtIndex: loc];
    [currScan next];
    return CHAR;
}
    
#define SKIPWHITESPACE {NSString *__dummy;  [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\t "] intoString: &__dummy];}
#define HANDLEFILEEND(X,Y) {NSString *err; if([X isAtEnd]){[self handleFileEnd]; if(Y){err = [NSString stringWithFormat: @"Unexpected file end in %@", [self hotSearchDocument]];  NSWARNING(err);} [qc setSource: [self hotSearchDocument]]; return ENDOFFILE;}}
-(void) scanForLN: (NSMutableString *) ans
{
    unsigned i,n;
    NSRange r;
    MWCHAR ch;
    int imode;
    n = [ans length];
    
  //look for a new line
    r = [ans rangeOfCharacterFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\r\n"] options: NSBackwardsSearch];
    if(r.location == NSNotFound) /*&& newlinecnt == 0)*/
    {
        r.location = -1;
    }
//    else if (r.location == NSNotFound)
 //       return;
    clnMode = YES; imode = 0;
    //read from there to end
    [clnBuff setString: @""];
    for(i = r.location + 1; i < n; i++)
    {
        ch = [ans characterAtIndex:i];
    //is it a number?
        if(ch >= '0' && ch <= '9' && (imode == 0 || imode == 1))
        {
            [clnBuff ADDCHAR(ch)];
            if(!imode) imode = 1;
        }
        else if (ch == '\t' && imode == 1)
        {
            cln = [clnBuff intValue];
            clnMode = NO;
            [clnBuff setString: @""];
            hasLineNumbers = YES;
            return;
        }
        else
        {
            
            clnMode = NO;
            [clnBuff setString: @""];
            cln = 0;
            return;
        }
    }
    
    // is it aa tab
        //else
    
}
-(int) parseString: (NSMutableString *) ans into: (ctQChar *) qc
{
    int r, n;
    
    if([ans length] == 0)
    {
        [qc addBuff: ans];
        [qc setTokenType: CHAR];
        //[qc setSource: [self hotSearchDocument]];

        return CHAR;
    }
    if([gPrefBoss TAScanForLN])
    {
        [self scanForLN: ans];
        
        //scan backwards for a return or cr
        //are there numbers after that?
        //is there a tab after that
    }
    if( ![self allowtab])
    {
        [ans replaceOccurrencesOfString: @"\t" withString: @"\\t" options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
    }
    if([self nopar])
    {
        n = [ans replaceOccurrencesOfString: @"\n" withString: @"\\n" options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
        r = [ans replaceOccurrencesOfString: @"\r" withString: @"\\n" options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
        //handle line numbering
        [self addNewLineCnt: n+r];
    }
    else
    {
        n = [ans replaceOccurrencesOfString: @"\n" withString: [NSString stringWithFormat: @"%c", getnewline()] options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
        r = [ans replaceOccurrencesOfString: @"\r" withString: [NSString stringWithFormat: @"%c", getnewline()] options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
        
        [self addNewLineCnt: n+r];
        
    }
    if(![self isquoteok])
    {
        [ans replaceOccurrencesOfString: @"\"" withString: @"\\Q" options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
        [ans replaceOccurrencesOfString: @"\'" withString: @"\\q" options: NSCaseInsensitiveSearch range: NSMakeRange(0, [ans length])];
    }         
    [qc addBuff: ans];
    [qc setTokenType: CHAR];
    //[qc setSource: [self hotSearchDocument]];

    return CHAR;
    
}
#define TAGSCANSTART 0
#define TAGSCANCODE 1
#define TAGSCANCODER 2
#define TAGSCANCOMMENT 3
#define TAGSCANLIMINAL 4

-(int) parseTag: (NSMutableString *) ans into: (ctQChar *) qc
{

    NSRange tr, cr, cmr;
    unsigned i,  n;
    int md;
    MWCHAR ch;
    
    tr.location = cr.location = cmr.location = 0;
    tr.length = cr.length = cmr.length = 0;
    n = [ans length];
    md = TAGSCANSTART;
    [qc setTokenType: TOKEN];
   for(i = 0; i< n; i++)
    {
        ch = [ans characterAtIndex: i];
        switch (md)
        {
            case TAGSCANSTART:
                if(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
                    break;
                if(ch == '!')
                {
                    [qc setTokenType: META];
                    break;
                }
                if(ch == '/' || ch == '\\')
                {
                    [qc setTokenType: ENDTOKEN];
                    break;
                }
                else
                {
                    tr.location = i;
                    tr.length = 1; //just in case there is no more
                }
                md = TAGSCANCODE;
                break;
                
            case TAGSCANCODE:
                
                if(isCharLegal(ch) == NO)
                {
                    if(ch == '[')
                    {
                        cr.location = i+1;
                        md = TAGSCANCODER;
                        break;
                    }
                    
                    md = TAGSCANLIMINAL;
                    tr.length = i - tr.location;
                    break;
                }
                break;
            case TAGSCANLIMINAL:
                if(ch == ' ' || ch == '\n' || ch == '\r' || ch == ':') break;
                if(ch == '[')
                {
                    cr.location = i+1;
                    md = TAGSCANCODER;
                    break;
                }
                md = TAGSCANCOMMENT;
                cmr.location = i;
                cmr.length = n -i;
                break;
                
            case TAGSCANCODER:
                if(ch == ']')
                {
                    cr.length = i - cr.location;
                    md = TAGSCANLIMINAL;
                    break;
                }
                    break;
                
            case TAGSCANCOMMENT:
                
                break;
            default:
                break;
                
        }
        
    }
   if(md == TAGSCANCODE) 
    {
       tr.length = n - tr.location;
    }
    if(tr.length > 0) [qc setBuff: [ans substringWithRange: tr]];
    if(cr.length > 0) [qc setCoder: [ans substringWithRange: cr]];
    if(cmr.length > 0) [qc setExtra: [ans substringWithRange: cmr]];
    return [qc tokentype];    
    
}

-(int) scanNext: (ctQChar *) qc withWarnings: (BOOL) warn
{
    NSString *tr;
    NSMutableString *ans;
    BOOL fnd;
    MWCHAR ch;
    int tst;
    [qc clean];
    //is there a current scanner?
    if([currScan scanLocation] == 0 || scanMode == SCANSTRING)
        [qc setWhere: [currScan scanLocation]];
    else
        [qc setWhere: [currScan scanLocation] - 1];
    //[qc setWhere: [self getCharLocation]];
    if(cln) [qc setLine: cln];
    if(scanEndFlag)
    {
        scanEndFlag = NO;
        [qc setSource: deadDataSource];
        scanMode = SCANSTRING;
        return ENDOFFILE;
    }
    else if(scanVeryEndFlag) 
    {
        [qc setSource: deadDataSource];
        return ENDOFALLFILES;
    }
    [qc setSource: [self hotSearchDocument]];
    [qc setBuff: @""];
    ans = [NSMutableString string];
    [ans setString: @""];
    switch(scanMode)
    {
        case SCANSTRING:
            if([self readEscape])//[gPrefBoss TAScanForLN])
            {
                while(1)
                {
                    fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\\{"] intoString: &tr];
                    if (fnd == NO)
                    {
                        tr = [NSMutableString string];
                    }
                    [ans appendString: tr];
                    if([currScan isAtEnd] == YES){ [qc setEnd: [currScan scanLocation]];[self handleFileEnd]; break;}
                    tst = [self scanNextChar: &ch];
                    if([currScan isAtEnd] == YES)
                    {
                        if(warn)NSWARNING(@"Probable error at end of file");
                        [qc setEnd: [currScan scanLocation]];
                        [self handleFileEnd];
                        break;
                    }
                    if(ch == '\\')
                    {
                        [ans ADDCHAR(ch)];
                        tst = [self scanNextChar: &ch];
                        [qc setEnd: [currScan scanLocation]];
                        [ans ADDCHAR(ch)];
                        if([currScan isAtEnd] == YES) 
                        {
                            [self handleFileEnd];
                            break;
                        }
                    }
                    else if(ch == '{')
                    {
                        scanMode = SCANTAG;
                        [qc setEnd: [currScan scanLocation] - 1];
                        //[self setCharLocation: [currScan scanLocation] - 1];
                        break;
                    }
                }
            }
            else
            {
                while(1)
                {
                    fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"{"] intoString: &tr];
                    if (fnd == NO)
                    {
                        tr = [NSMutableString string];
                    }
                    [ans appendString: tr];
                    if([currScan isAtEnd] == YES){[qc setEnd: [currScan scanLocation]];[self handleFileEnd]; break;}
                    tst = [self scanNextChar: &ch];
                    if([currScan isAtEnd] == YES)
                    {
                        [qc setEnd: [currScan scanLocation]];
                        if(warn)NSWARNING(@"Probable error at end of file");
                        [self handleFileEnd];
                        break;
                    }
                    if(ch == '{')
                    {
                        [qc setEnd: [currScan scanLocation] - 1];
                        scanMode = SCANTAG;
                        //[self setCharLocation: [currScan scanLocation] - 1];
                        break;
                    }
                }
            }
            [self setLoc];
            return [self parseString: ans into: qc];
            break;

            
        case SCANTAG:
            if([self readEscape])//[gPrefBoss TAScanForLN])
            {
                BOOL inquote;
                inquote = NO;
                while(1)
                {
                    if(inquote == NO)
                    {
                        fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\"}\\"] intoString: &tr];
                    }
                    else
                    {
                        fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\""] intoString: &tr];
                        
                    }


                    if (fnd == NO)
                    {
                        tr = [NSMutableString string];
                    }
                    [ans appendString: tr];
                    if([currScan isAtEnd] == YES)
                    {
                        [qc setEnd: [currScan scanLocation]];
                        [self handleFileEnd]; 
                        if(warn)NSWARNING(@"Tag missing close brace at end of file");
                        break;
                    }
                    tst = [self scanNextChar: &ch];
                    if([currScan isAtEnd] == YES && ch == '"')
                    {
                        [ans ADDCHAR(ch)];
                        scanMode = SCANSTRING;
                        [qc setEnd: [currScan scanLocation]];

                        if(warn)NSWARNING(@"Tag missing close brace at end of file");
                        [self handleFileEnd];
                        break;
                    }
                    if([currScan isAtEnd] == YES && ch == '\\')
                    {
                        [qc setEnd: [currScan scanLocation]];
                        scanMode = SCANSTRING;
                        if(warn)NSWARNING(@"Tag missing close brace at end of file");
                        [self handleFileEnd];
                        break;
                    }
                    if(ch == '\\')
                    {
                        [ans ADDCHAR(ch)];
                        tst = [self scanNextChar: &ch];
                        [ans ADDCHAR(ch)];
                        if([currScan isAtEnd] == YES) 
                        {
                            [qc setEnd: [currScan scanLocation]];
                            scanMode = SCANSTRING;
                            [self handleFileEnd];
                            break;
                        }//else continue
                    }
                    if(ch == '"')
                    {
                        [ans ADDCHAR(ch)];
                        if([currScan isAtEnd] == YES) 
                        {
                            [qc setEnd: [currScan scanLocation]];
                            scanMode = SCANSTRING;
                            [self handleFileEnd];
                            break;
                        }
                        else
                        {
                            if(inquote == YES) inquote = NO; else inquote = YES;
                            continue;
                        }
                    }
                    else if(ch == '}')
                    {
                        [qc setEnd: [currScan scanLocation]];
                        if([currScan isAtEnd] == YES) [self handleFileEnd];
                        scanMode = SCANSTRING;
                        break;
                    }
                    //else break; //there's some sort of error!
                }
            }
            else
            {
                    BOOL inquote;
                    inquote = NO;
                while(1)
                {
                    if(inquote == NO)
                    {
                        fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\"}\\"] intoString: &tr];
                    }
                    else
                    {
                        fnd = [currScan scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString: @"\""] intoString: &tr];
                        
                    }
                    if (fnd == NO)
                    {
                        tr = [NSMutableString string];
                    }
                    [ans appendString: tr];
                    if([currScan isAtEnd] == YES)
                    {
                        scanMode = SCANSTRING;
                        [qc setEnd: [currScan scanLocation]];
                        [self handleFileEnd]; 
                        if(warn) NSWARNING(@"Tag missing close brace at end of file");
                        break;
                    }
                    tst = [self scanNextChar: &ch];
                    if([currScan isAtEnd] == YES && ch == '\"')
                    {
                        [ans ADDCHAR(ch)];
                        scanMode = SCANSTRING;
                        if(warn) NSWARNING(@"Tag missing close brace at end of file");
                        [qc setEnd: [currScan scanLocation]];
                        [self handleFileEnd];
                        break;
                    }
                    if(ch == '"')
                    {
                        [ans ADDCHAR(ch)];
                        if([currScan isAtEnd] == YES) 
                        {
                            [qc setEnd: [currScan scanLocation]];
                            scanMode = SCANSTRING;
                            [self handleFileEnd];
                            break;
                        }
                        else
                        {
                            if(inquote == YES) inquote = NO; else inquote = YES;
                            continue;
                        }
                    }
                    if(ch == '}')
                    {
                        [qc setEnd: [currScan scanLocation]];
                       if([currScan isAtEnd] == YES) [self handleFileEnd];
                        scanMode = SCANSTRING;
                        break;
                    }

                }
            }
            [self setLoc];
            //scanMode = SCANSTRING;
            return [self parseTag: ans into: qc];
            break;
    }
    return 0;
    
}
-(int) scanNext: (ctQChar *) qc
{
    return [self scanNext: qc withWarnings: YES];
}
#endif
-(int) readnext: (ctQChar *)qc
{
	MWCHAR c;
	int i;
	int meta;
	int etag;
	c = [self getNextChar]; 
	[qc setBuff: @""];
	[qc setExtra: @""];	
	[qc setCoder: @""];
	[qc setWhere: dsLen - 1];
	if(c != '{' /*|| ([gCurrentTAMS global: @"startflag"] == 0)*/)
	{
		/* situation normal */
                
                //handle line numbering
                if([gPrefBoss TAScanForLN])
                {
                    if(clnMode == YES)
                    {
                        if(c== '\t')
                        {
                            cln = [clnBuff intValue];
                            clnMode = NO;
                            [clnBuff setString: @""];
                            hasLineNumbers = YES;
                        }
                        else if(c >= '0' && c <= '9')
                        {
                            [clnBuff ADDCHAR(c)];
                        }
                        else
                        {
                            clnMode = NO;
                            [clnBuff setString: @""];
                            cln = 0;
                        }
                    }
                    
                    else if(isnewline(c))
                    {
                        clnMode = YES;
                    }
                
                
                }

		if(isnewline(c)) [self incnewlinecnt];
		
		if ([self getEOF])
		{
			return EOF;
		}
		if(isnewline(c) && [self nopar])
		{
		    [qc setBuff: @"\\n"];
		}
		else if(isnewline(c) && getnewline())
		{
		    c = getnewline();
		}
		else if(c == '\t' && ! [self allowtab])
		{
		    [qc setBuff: @"\\t"];
		}
		else if(c == '\"' && ![self isquoteok])
		{
		    [qc setBuff: @"\\Q"];
		}
		else if(c == '\'' && ![self isquoteok])
		{
		    [qc setBuff: @"\\q"];
		}
                else if(c == '\\' && [self readEscape])
                {
                    [[qc buff] ADDCHAR([self getNextChar])];
                }
		else
		
		{
			[[qc buff] ADDCHAR(c)];
		}
		[qc setTokenType: CHAR];

		return 1;
	}

	/* we're in a tag so read the name */
	i =0;
	c = [self getNextChar];
	[qc setTokenType: TOKEN];
        if(cln) [qc setLine: cln];
	meta = etag = 0;
	if(c == '!') {meta = 1; [qc setTokenType: META];}
	else if(c == '\\' || c == '/') 
	{
	    etag =1; 
	    [qc setTokenType: ENDTOKEN]; 
	    [qc setExtra: @""];
	}
	else
	{	if(c == '{') NSWARNING(CLOSEBRACEERR);
		[[qc buff] ADDCHAR(c)];
	}
	{ //this is for everyone to read in the name

		for(;;)
		{
			c = [self getNextChar];//fgetc(getcurrfile());
			if(!isCharLegal(c))
                            //(isalnum(c) || c == '_' || c == SCHAR) )
			{
				
				break;
			}
			else
			{
			    [[qc buff] ADDCHAR(c)];
			}
		}
	}
	if(c == ' ') while((c = [self getNextChar]) == ' ') ;
        if(c == '{') NSWARNING(CLOSEBRACEERR);
	if(c == '[')
	{
	    while((c = [self getNextChar]) != ']')
		[[qc coder] ADDCHAR(c)];
	    c = [self getNextChar];
            
	}
	if(c == ' ') while((c = [self getNextChar]) == ' ');
	if(c == '}') return [qc tokentype];
	if (c == ':' || c == ' ' || c == ';') c = [self getNextChar];
	//else [[qc extra] ADDCHAR (c)];
	{	//this block is for reading the rest of the message
		int startflag;
		startflag = 1;
		i = 0;
		do
		//while((c = [self getNextChar]) != '}')
		{
		    if(startflag && c == ' ') continue;
		    startflag = 0;
		    //if(c == '}') break;
		    [[qc extra] ADDCHAR(c)];
		    if(c == '\"') //read til you find another
		    {
			while((c = [self getNextChar]) != '\"' && [self getEOF] == NO)
			    [[qc extra] ADDCHAR(c)];
			if([self getEOF] == NO) [[qc extra] ADDCHAR(c)];
                        
		    }
                    if(c == '{') NSWARNING(CLOSEBRACEERR);

		}
		while((c = [self getNextChar]) != '}' && [self getEOF] == NO);
	}
	//if([qc tokentype] == ENDTOKEN) [qc setWhere: dsLen];
	return [qc tokentype];
}

-(NSString *) reformatString //string is set at init time
{
    ctQChar *qq = [[ctQChar alloc] init];
    NSMutableString *ans = [NSMutableString string];
    
    while([self readnext: qq] != EOF && [self getEOF] == NO)
    {
        if([qq tokentype] == META)
        {
            if([[qq buff] isEqualToString: @"end"] == YES || 
                [[qq buff] isEqualToString: @"endsection"])
                ;
            else
                continue;
        }
        [ans appendString: stringForQChar(qq, NO)];
    }
    return ans;
}

-(int) readQChar: (ctQChar *) qc atIndex: (int) where
{
    int cloc;
    int ans;
    
    cloc = [self getCharLocation];
    [self setCharLocation: where];
    ans = [self readnext: qc];
    [self setCharLocation: where];
    return ans;
}

-(MWCHAR) readCharAtIndex: (unsigned) where
{
    
    return [gTheData characterAtIndex: where];
}


/*
    Functions for ctunlimitedruns
*/



-(void) ctInitRV
{
    if(ctRunVault)
    {
	if(ctRunVault)
	    [ctRunVault release];
	//we may need to get rid of this stuff
	// [ctRunVault removeAllObjects];
    }
    ctRunVault = [[NSMutableArray alloc] init];
    [ctRunVault retain];
}

-(void) ctAddOpenChar:(ctQChar *)qq
{
	FORALL(ctRunVault)
	{
	    if(([temp openRun] == YES) /*&& !isrepeat(qq)*/)
	    {
		switch([qq tokentype])
		{
		    case CHAR:
			[(coderec *)temp addString: [qq buff]];
			break;
		    case TOKEN:
			if([self israw] && ( [gCurrentTAMS isRepeat: [temp theName]] == NO))
			{
			    [(coderec *)temp addString: @"{"];
			    [(coderec *)temp addString: [qq buff]];
			    //add coder
			    PRINTCODER((coderec *)temp, [qq coder]);
			    [(coderec *)temp addString: @"}"];
			}
			break;
		    case ENDTOKEN:
			if([self israw] && ( [gCurrentTAMS isRepeat: [temp theName]] == NO))
			{
			    [(coderec *)temp addString: @"{/"];
			    [(coderec *)temp addString: [qq buff]];
			    //add coder
			    PRINTCODER((coderec *)temp, [qq coder]);
                            if([temp runType] == SECTIONRUN && 
                                [[qq extra] isEqualToString: @""] == NO)
                                    [(coderec *) temp addString: [NSString stringWithFormat: @": %@",
                                        [qq extra]]];
			    [(coderec *)temp addString: @"}"];
			}
		    
		    default:;
		};
			
			    
	    }
	}
	ENDFORALL;
}

-(int) isrepeat: (ctQChar *)qq
{
    if(gCurrentTAMS)
	return [gCurrentTAMS isRepeat: [qq buff]];
    else
	return 0;
}
-(void) ctOpenRepeatRun: (ctQChar *)qq
{
    coderec *cr;
    
   /* if ([self isrepeat: qq] && ![self issimple]) return;*/
    cr = [[coderec alloc] init];
    
   [cr setName: [qq buff]];
    [cr setBegin: [qq where]];
    [cr setCoder: [qq coder]];
    [cr setLineStart: [qq line]];
    [cr setDoc: hotSearchDocument];
    [cr setOpen: YES];
    [cr setRunType: REPEATRUN];
     [cr autorelease];
  [ctRunVault addObject: cr];
    //need to add current state at this point!
    //need to add self tothe current state
}
#ifdef SECTIONSEARCH
-(BOOL) hasSectionRun
{
    FORALL(ctRunVault)
    {
        
	if( [(coderec *)temp runType] == SECTIONRUN) return YES;    
    }
    ENDFORALL;
    
    return NO;
}

-(void) ctCloseSectionTagForCode: (NSString *) mycode Coder: (NSString *) mycoder
{
    coderec *who;
    NSMutableArray *myCodes;
    
    who = [self hotSectionRun];
    if(who == nil) return;
    myCodes = [who sectionCodes];
    FORALL(myCodes)
    {
        if([[temp objectForKey: @"code"] isEqualToString: mycode] && 
            [[temp objectForKey: @"coder"] isEqualToString: mycoder])
        {
            if([[temp objectForKey: @"state"] isEqualTo: @"Open"])
            {
                [temp setObject: @"Closed" forKey: @"state"];
            }
        }
         
    }
    ENDFORALL;


}
-(void) ctAddSectionTag: (NSMutableDictionary *) md
{
    coderec *who;
    NSMutableArray *myCodes;
    
    who = [self hotSectionRun];
    myCodes = [who sectionCodes];
    FORALL(myCodes)
    {
        if([[temp objectForKey: @"code"] isEqualToString: [md objectForKey:@"code"]] && 
            [[temp objectForKey: @"coder"] isEqualToString: [md objectForKey: @"coder"]])
        {
            if([[temp objectForKey: @"state"] isEqualTo: @"Closed"])
            {
                [temp setObject: @"Open" forKey: @"state"];
                return;
            }
        }
         
    }
    ENDFORALL;
    [myCodes addObject: md];
    

}
-(coderec *) hotSectionRun
{
    FORALL(ctRunVault)
    {
        if([temp runType] == SECTIONRUN) return temp;
    }
    ENDFORALL;
    return nil;
}

-(coderec *) ctOpenSectionRun
{
    coderec *cr;
    
   /* if ([self isrepeat: qq] && ![self issimple]) return;*/
    cr = [[coderec alloc] init];
        
   [cr setName: @""];
    [cr setBegin: [self getCharLocation]];
    [cr setCoder: @""];
    [cr setDoc: hotSearchDocument];
    [cr setOpen: YES];
        [cr setRunType: SECTIONRUN];
    [self cleanUpTagVault];
    [[cr sectionCodes] addObjectsFromArray: tagVault];
    [cr autorelease];
   [ctRunVault addObject: cr];
    //need to add current state at this point!
    //need to add self tothe current state
    return cr;
}

-(void) cleanUpTagVault
{
    NSALLOC(NSMutableArray, tempAr);
    
    
    FORALL(tagVault)
    {
        if([[temp objectForKey: @"state"] isEqualToString: @"Closed"] == YES)
            [tempAr addObject: temp];
    }
    ENDFORALL;
    FORALL(tempAr)
    {
        [tagVault removeObject: temp];
    }ENDFORALL
    ;
    [tempAr release];
    //[tagVault removeAllObjects];
}
-(void) ctCloseSectionRun
{
    FORALL(ctRunVault)
    {
        
	if( ([(coderec *)temp runType] == SECTIONRUN) &&( [temp openRun] == YES)) //add coder here too
	{
            [self cleanUpTagVault];
            [tagVault addObjectsFromArray: [temp sectionCodes]];
	    [temp setOpen: NO];
	    [temp setEnd: [self getCharLocation]];
	    return;
	}
    
    }
    ENDFORALL;
    //need to check out of the current state
}
-(BOOL) hasLimit
{
    if([ctLimitVault count]) return YES;
    else return NO;
}

-(int) checkAnd:  (NSArray *) andGrp forSection: (NSMutableArray *) sCodes
{
    int ans;
    ans = 1; 
    
    FORALL(andGrp)
    {
        if([self isCurrSectionCode:temp forSectionArray:sCodes]) ans = ans *1;
        else ans = ans *0;
    }
    ENDFORALL;
    if(ans) return 1;
    else return 0;
}

-(BOOL) isSectionRunOK: (coderec *) who
{
    int ans;
    ans = 0;
    
    FORALL(ctLimitVault)
    {
        ans+=  [self checkAnd:  (NSArray *)temp forSection: (NSMutableArray *) [who sectionCodes]];

    }
    ENDFORALL;
    if(ans) return YES;
    else return NO;
}
-(void) filterSectionRuns
{
    NSALLOC(NSMutableArray, deleteme);
	if([self hasLimit] == NO)
        {
            [deleteme release];
            return;
        }
	FORALL(ctRunVault)
	{
            if([temp runType] == SECTIONRUN)
                if([self isSectionRunOK: temp] == NO)
                    [deleteme addObject: temp];/*            {
                int i, j, n;
                NSArray *ma;
                NSString *what;
                ma = [temp sectionCodes];
                n = [ma count];
                for(i = 0; i < n; i++)
                    what = [[ma objectAtIndex: i] objectForKey: @"code"];
            }*/
                
            

	}ENDFORALL;
    [ctRunVault removeObjectsInArray: deleteme];
    [deleteme release];
}

#endif
-(void) ctOpenRun: (ctQChar *)qq
{
    coderec *cr;
    
   /* if ([self isrepeat: qq] && ![self issimple]) return;*/
   if([gCurrentTAMS isBlocked: [qq buff]] == YES) return;
    cr = [[coderec alloc] init];
    
     if([self israw] && ![self isrepeat:qq])
    {
	
	FORALL(ctZoneVault)
	{
	    [[cr record] appendString: @"{"];
	    [[cr record] appendString: [temp objectForKey: @"codeName"]];
	    //add coder
	    PRINTCODER([cr record], [temp objectForKey:@"coderName"]);
	    [[cr record] appendString: @"}"];
	}ENDFORALL;
    }
    
   [cr setName: [qq buff]];
    [cr setBegin: [qq where]];
    [cr setCoder: [qq coder]];
    [cr setLineStart: [qq line]];
    [cr setDoc: hotSearchDocument];
    [cr setOpen: YES];
     if([self isrepeat: qq]) 
        [cr setRunType: REPEATRUN];
    [cr autorelease];
   [ctRunVault addObject: cr];
    //need to add current state at this point!
    //need to add self tothe current state
}

-(void) ctCloseAllOpenRuns
{
   FORALL(ctRunVault)
    {
	if([temp openRun] == YES)
	{
	    if([self israw])
	    {
		[[temp record] appendString: @"{/EOF}"];
	    }
	    [temp setOpen: NO];
	    [temp setComment: @"End of file found without close tag"];
	    [temp setEnd: [self getCharLocation]];
	}
    
    }
    ENDFORALL;
    //need to check out of the current state


}
-(void) ctCloseRun: (ctQChar *)qq
{
    FORALL(ctRunVault)
    {
	if(([[(coderec *)temp theName] isEqualToString: [qq buff]] == YES) &&( [temp openRun] == YES) && ([[(coderec *) temp theCoder] isEqualToString: [qq coder]])) //add coder here too
	{
	    if([self israw] && ( [gCurrentTAMS isRepeat: [temp theName]] == NO))
	    {
		[[temp record] appendString: @"{/"];
		[[temp record] appendString: [qq buff]];
		//add coder
		PRINTCODER([temp record], [qq coder]);
		[[temp record] appendString: @"}"];
	    }
	    [temp setOpen: NO];
	    [temp setComment: [qq extra]];
	    [temp setEnd: [qq where]];
	    return;
	}
    
    }
    ENDFORALL;
    //need to check out of the current state
}
-(int) issimple
{
    if (gCurrentTAMS)
	return [gCurrentTAMS global: @"simpleflag"];
    else return 0;
}

-(int) israw
{
    if (gCurrentTAMS)
	return [gCurrentTAMS global: @"rawflag"];
    else return 0;
}


/* functions from ctlimitfunc */

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

-(NSMutableArray*) ctRunVault{return ctRunVault;}

-(NSMutableArray *) ctZoneVault {return ctZoneVault;}
-(void) setGCurrentTAMS: (id) who {gCurrentTAMS = who;}
-(id) gCurrentTAMS {return gCurrentTAMS;}

//zone management

-(void) ctAddZone: (ctQChar *)who
{
    NSMutableDictionary *dd;
    dd = [[NSMutableDictionary alloc] init];
    [dd setObject: [[who buff] copy] forKey: @"codeName"];
    [dd setObject: [[who coder] copy] forKey: @"coderName"];
    
    [ctZoneVault addObject:dd];
}

-(void) ctAddLimChar:(ctQChar *)qq
{
	FORALL(ctRunVault)
	{
	    if(([temp openRun] == YES) /*&& !isrepeat(qq)*/)
	    {
		switch([qq tokentype])
		{
		    case CHAR:
			[(coderec *)temp addString: [qq buff]];
			break;
		    case TOKEN:
			if([self israw] && 
                            [(coderec *) temp  runType] != REPEATRUN  /*([gCurrentTAMS isRepeat: [temp theName]] == NO)*/)
			{
			    [(coderec *)temp addString: @"{"];
			    [(coderec *)temp addString: [qq buff]];
			    
			    //add coder
			    PRINTCODER((coderec *)temp, [qq coder]);
			    if([[qq coder] length])
			    {[(coderec *)temp appendString:@"["]; 
				[(coderec *)temp appendString: [qq coder]]; 
				[(coderec *)temp appendString: @"]"];}
			    [(coderec *)temp addString: @"}"];
			}
			break;
		    case ENDTOKEN:
			if([self israw] && ([gCurrentTAMS isRepeat: [temp theName]] == NO))
			{
			    [(coderec *)temp addString: @"{/"];
			    [(coderec *)temp addString: [qq buff]];
			    //add coder
			    PRINTCODER((coderec *)temp, [qq coder]);
			    [(coderec *)temp addString: @"}"];
			}
		    
		    default:;
		};
			
			    
	    }
	}
	ENDFORALL;
}

-(void) ctOpenLimRun:(ctQChar *)qq
{
    coderec *cr;
    
    cr = [[coderec alloc] init];
    [cr setLineStart: [qq line]];
     if([self israw] /*&& ![self isrepeat: qq]*/)
    {
	
	FORALL(ctZoneVault)
	{
	    [[cr record] appendString: @"{"];
	    [[cr record] appendString: [temp objectForKey: @"codeName"]];

	    if([[temp objectForKey: @"coderName"] isEqualToString: @""] == YES)
		;
	    else //add coder
	    {
		PRINTCODER([cr record], [temp objectForKey: @"coderName"]);
	    }
/* old code
	    {
		[[cr record] appendString: @"["];
		[[cr record] appendString: [temp objectForKey: @"coderName"]];
		[[cr record] appendString: @"]"];
	    }
	    
*/
	    [[cr record] appendString: @"}"];
	}ENDFORALL;
    }
    
    if(singleLimFlag)
    {
	NSMutableString *sss = [[NSMutableString alloc] init];
	[sss setString: @"+"];
	[sss appendString: [qq buff]];
	[cr setName: sss];
    }
    else
    {
	NSMutableString *sss = [[NSMutableString alloc] init];
	[sss setString: @"-"];
	[sss appendString: [gCurrentTAMS limString]];
	[cr setName: sss];
	
    }
    [cr setBegin: [qq where]];
    [cr setDoc: hotSearchDocument];

    [cr setOpen: YES];
    [cr autorelease];
    [ctRunVault addObject: cr];
    //need to add current state at this point!
    //need to add self tothe current state
}
-(void) ctCloseLimRun:(ctQChar *)qq
{
    if([self israw])
    {
	FORALL(ctRunVault)
	{
	    if([temp openRun] == YES && ([gCurrentTAMS isRepeat: [temp theName]] == NO))
	    {
		[[temp record] appendString: @"{/"];
		[[temp record] appendString: [qq buff]];
		//add coder
		PRINTCODER([temp record], [qq coder]);
		[[temp record] appendString: @"}"];
	    }
	}
	ENDFORALL;
    }

    FORALL(ctRunVault)
    {
	if([temp openRun] == YES && ([gCurrentTAMS isRepeat: [temp theName]] == NO) )
	{
	    [temp setOpen: NO];
	    [temp setEnd: [qq where]];
	    [temp setComment: [qq extra]];
	    return;
	}
    
    }
    ENDFORALL;
    //need to check out of the current state
}

-(void) checkZones
{
    if([ctZoneVault count])
	NSWARNING(@"There are passages missing a close tag; run \"check code pairs\" on your files");
}
-(void) ctDelAllZones
{
    [ctZoneVault removeAllObjects];
}
-(void) ctDelZone:(ctQChar *)who
{
    id theOne;
    FORALL(ctZoneVault)
    {
	theOne = nil;
	if([[temp objectForKey: @"codeName"] isEqualToString: [who buff]] &&
	    [[temp objectForKey: @"coderName"] isEqualToString: [who coder]])
	{
	    theOne = temp;
	    break;
	}
    }
    ENDFORALL;
    
    if (theOne != nil)
	[ctZoneVault removeObject: theOne];
    else NSWARNING(@"There are formatting errors in your file; run check code pairs");
    //[theOne release];
}

-(int) handleLimChar:(ctQChar *)qq
{
    if([qq tokentype] == META) [gCurrentTAMS handlemeta: qq];
    if([qq tokentype] == TOKEN)
    {
//        if([gPrefBoss nonSimpleRepeatValue] == 0 && [self isrepeat: qq] && ![self issimple])
            ;
//            else
                [self ctAddZone: qq];
        
        
	if([gCurrentTAMS isRepeat: [qq buff]] && ([gCurrentTAMS isBlocked: [qq buff]] == NO))
	{
	    [self ctOpenRepeatRun: qq];
            if([gPrefBoss nonSimpleRepeatValue] == 0 && ![self issimple]) 
            {
                if(inLimFlag == 1) return INLIM;
                else return OUTLIM;
            }
	}
        
    }
    else if([qq tokentype ] == ENDTOKEN)
    {
	[self ctDelZone:qq];
	if([gCurrentTAMS isRepeat: [qq buff]] && ([gCurrentTAMS isBlocked: [qq buff]] == NO))
	{
	    [self ctCloseRun: qq];
	}
    }
    else if([qq tokentype] == CHAR)
    {
	if(inLimFlag)
	    return INLIM;
	else
	{
	    [self ctAddOpenChar: qq];  //cludge for repeats
	    return OUTLIM;
	}
    }
    if(inLimFlag == 0 && [self isinlimit])
    {
	inLimFlag = 1;
	return STARTLIM;
    }
    else if(inLimFlag == 1 && [self isinlimit])
    {
	return INLIM;
    }
    else if (inLimFlag == 0 && ![self isinlimit])
    {
	return OUTLIM;
    }
    else if (inLimFlag == 1 && ![self isinlimit])
    {
	inLimFlag = 0;
	return ENDLIM;
    }
    return OUTLIM;
}

-(void) zeroRuns
{
    ctLimitVault = nil;
    ctZoneVault = nil;
    ctLimString = nil;
}
-(void) initLimit
{
    if(ctLimitVault) [ctLimitVault release];
    
    ctLimitVault = [[NSMutableArray alloc] init];
   //[ctLimitVault retain];
   if(ctLimString) [ctLimString release];
    ctLimString = [[NSMutableString alloc] init];
    if(ctZoneVault) [ctZoneVault release];
    ctZoneVault = [[NSMutableArray alloc] init];
    inLimFlag = 0;
}

-(int) isStringTrue: (ctLimitCrit *)elem withCode: (NSString *)code withCoder: (NSString *)coder;
{
    NSMutableArray *aa;
    NSRange rr;
		//get help from the current tams object
    NSMutableArray *bb;
    int matchflag;
    int lcnt;
    int ii, jj;
    int ncnt,tcnt;
   //first find out if we match the coder
    if([elem areCoders]==YES) //check coder against everyone
    {
	int foundFlag;
	NSRange r;
	foundFlag = 0;
	FORALL([elem getCoders])
	{
	    NSString *s1 = [NSString stringWithString: [temp objectForKey: @"coderName"]];
	    if([s1 isEqualToString: coder]) ii++;
	    if([[temp objectForKey: @"modifier"] isEqualToString: @"~"] == YES)
	    {
		//just check out the front part
		r = [coder rangeOfString: [temp objectForKey: @"coderName"]];
		if(r.location == 0)
		{
		    foundFlag = 1; break;
		}
	    }
	    else
	    {
		//check out the rest, but make sure to do a null string check
		if([[temp objectForKey: @"coderName"] isEqualToString: @"*"] == YES)
		{
		    if([coder isEqualToString: @""] == YES)
		    {
			foundFlag = 1; break;
		    }
		}
		else
		{
		    if([coder isEqualToString: [temp objectForKey: @"coderName"]])
		    {
			foundFlag = 1; break;
		    }
		}
		    
	    }
	}
	ENDFORALL;
	if(!foundFlag) return 0;
    }
    if([[elem name] isEqualToString: @""] == YES) return 1;
 	switch([elem modif])
	{
	    case '>':
		//get help from the current tams object

		    matchflag = 1;
		    aa = convertStringToArray(code, '>');
		    bb = convertStringToArray([elem name], '>');
		    [aa retain]; [bb retain];
		    ncnt = [bb count];
		    tcnt = [aa count];
		    if(ncnt > tcnt)  //the string must be equal at least to the test name
		    {
			matchflag = 0;
		    }
		    else
		    {
			for(ii = 0; ii <= tcnt - ncnt; ii++)
			{
			    matchflag = 1;
			    for(lcnt = 0, jj = ii; lcnt < ncnt; lcnt++, jj++)
			    {
				if([[bb objectAtIndex: lcnt] isEqualToString:
					[aa objectAtIndex: jj]] == NO)
				{
				    matchflag = 0;
				    break;
				}
			    }
			    if(matchflag == 1) return matchflag;
			}
		    }
		    if(matchflag) return matchflag;
		    //loop on bb, aa can be longer
		    //if ([[aa objectAtIndex: 0] isEqualToString: [elem name]])
			//return 1;
		    break;
	    case '*':
		rr = [code rangeOfString: [elem name]];
		if(rr.location != NSNotFound)
		    return 1;
		break;
	    case '\'':
		 if([code isEqualToString: [elem name]] == YES)
			return 1;
		break;
	    default:
		if([gCurrentTAMS global: @"exactflag"])
		{
		    if([code isEqualToString: [elem name]] == YES)
			return 1;
		}
		else
		{
		    NSMutableArray *bb;
		    int matchflag;
		    int lcnt;
		    int ncnt,tcnt;
		    matchflag = 1;
		
		    aa = convertStringToArray(code, '>');
		    bb = convertStringToArray([elem name], '>');
		    [aa retain]; [bb retain];
		    ncnt = [bb count];
		    tcnt = [aa count];
		    if(ncnt > tcnt)  //the zone must be equal at least to the test name
		    {
			matchflag = 0;
		    }
		    else
		    {
			for(lcnt = 0; lcnt < ncnt; lcnt++)
			{
			    if([[bb objectAtIndex: lcnt] isEqualToString:
				    [aa objectAtIndex: lcnt]] == NO)
			    {
				matchflag = 0;
				break;
			    }
			}
		    }
		    if(matchflag) return matchflag;
		    //loop on bb, aa can be longer
		    //if ([[aa objectAtIndex: 0] isEqualToString: [elem name]])
			//return 1;
		}
		break;
	}
	;
    return 0;
}
//compare this andgroup with the current list of codes and coders
-(int) isCurrSectionCode:(ctLimitCrit *)elem forSectionArray: (NSMutableArray *) who
{
    
    FORALL(who)
    {
	if([self isStringTrue: elem withCode: [temp objectForKey: @"code"] withCoder: [temp objectForKey: @"coder"]]) return 1;
    } ENDFORALL;
    return 0;
}
//compare this andgroup with the current zone
-(int) isCurrTrue:(ctLimitCrit *)elem
{
    
    FORALL(ctZoneVault)
    {
	if([self isStringTrue: elem withCode: [temp objectForKey: @"codeName"] withCoder: [temp objectForKey: @"coderName"]]) return 1;
    } ENDFORALL;
    return 0;
}

-(int) isTagTrue:(ctQChar *)who
{
    int i,j, c1, c2;
    ctLimitCrit *elem;
    NSArray *andList;
    
    c1 = [ctLimitVault count];
    for(i = 0; i< c1; i++)
    {
	andList = [ctLimitVault objectAtIndex: i];
	c2 = [andList count];
	for(j = 0; j < c2; j++)
	{
	    elem = [andList objectAtIndex: j];
	    if([self isStringTrue: elem withCode: [who buff] withCoder: [who coder]]) return 1;
	}
    }
    return 0;

}

-(int) checkand:(NSArray *)a
{
	int r, oldr; 
	oldr = 1;
	FORALL(a)
	{
		r = [self isCurrTrue: temp];
		oldr *= r; //and is like times if any are 0 it goes to 0
	}
	ENDFORALL;
	return oldr ;
}



-(int) isinlimit
{
	int   rslt;
	int trslt;
	trslt = 0;
	if([ctZoneVault count] == 0) return 0;
	FORALL(ctLimitVault)
	{
	    rslt = [self checkand: temp];
	    trslt += rslt;
	    if(trslt) { return 1;}
	
	}
	ENDFORALL;
        if([ctLimitVault count] == 0) return 1; //this is a test of non-simple unlimited searches
	return 0;
}
/* handlers */

-(void) parseand:(NSString *)nsbuff
{
	int i, j;
	MWCHAR c;
	NSMutableString *b;
	ctLimitCrit *elem;
	NSMutableArray *agp;
	
#ifdef ldebug
	printf("in parseand: %s\n", buff);
#endif
	agp = [[NSMutableArray alloc] init]; //agp = (andgroup *) new andgroup;
	b = [[NSMutableString alloc] init];
	[b retain];
	
	i = j = 0;
	for(;;)
	{
		if(i >= [nsbuff length]) c = '\0';
		else
		    c = [nsbuff characterAtIndex: i];
		if(c == ' ') {i++; continue;}
		if(c == '+' || c == '\0')
		{
			if([b length])
			{
				elem = [[ctLimitCrit alloc] initWithString: b];
				[elem retain];
				[agp addObject: elem];
				//[elem release];
			}
			j = 0;
			[b setString: @""];
			if (c == '\0') break;
		}
		else
		    [b ADDCHAR(c)];
		i++;
	}
	[ctLimitVault addObject: agp];
	//[agp release];
	[b release];
}

-(void) handlelimit:(NSString *)buff
{
	MWCHAR c;
	unsigned i, j, n;
	NSMutableString *b;
	
	singleLimFlag = 0;
	[ctLimString setString: buff];
	b = [[NSMutableString alloc] init];
	[b retain];
	n = [buff length];
	if(n)
	{
		[gCurrentTAMS setGlobal: @"limitflag" to: 1];
		i = 0;
		j = 0;
		for(;;)
		{
			if(i >= [buff length]) c = '\0';
			else
			    c = [buff characterAtIndex: i];
			if(c  == ' ') 
			{
			    i++; 
			    if(i >= [buff length]) break; 
			    c = [buff characterAtIndex: i];
			}
			
			if(i >= n) break;
			while(c  != ',' && i < n)
			{
				[b ADDCHAR(c)]; i++; j++;
				if(i < n)
				    c = [buff characterAtIndex: i];
				else
				    break;
			}
			
			if ([b length]) {[self parseand: b]; [b setString: @""];}
			if (c == '\0') break;
			i++;
		}
	}
	if([ctLimitVault count] == 1)
	{
	    NSArray *theOne;
	    //may be a single name search
	    theOne = [ctLimitVault objectAtIndex: 0];
	    //passes test 1
	    if([theOne count] == 1)
	    {
		if([[theOne objectAtIndex: 0] modif] == ' ')
		{
		    singleLimFlag = 1;
		}
	    
	    }
	
	
	}
}



@end
