// // 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 #include "newline.h" #include #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