// // ctLimitFunc.m // CocoaTams // // Created by matthew on Mon Apr 15 2002. // Copyright (c) 2001 Matthew Weinstein. All rights reserved. // #import "ctLimitFunc.h" #import "ctLimitCrit.h" #import "tams.h" #import "utils.h" #import "ctQChar.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: @"]"];}} NSMutableString *ctLimString; NSMutableArray *ctLimitVault; NSMutableArray *ctZoneVault; int inLimFlag = 0; int singleLimFlag; //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(israw() && ([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(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]; if(israw() && !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 retain]; [ctRunVault addObject: cr]; //need to add current state at this point! //need to add self tothe current state } void ctCloseLimRun(ctQChar *qq) { if(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(void) { 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) { ctAddZone(qq); if([gCurrentTAMS isRepeat: [qq buff]]) { ctOpenRun(qq); } } else if([qq tokentype ] == ENDTOKEN) { ctDelZone(qq); if([gCurrentTAMS isRepeat: [qq buff]]) { ctCloseRun(qq); } } else if([qq tokentype] == CHAR) { if(inLimFlag) return INLIM; else { ctAddOpenChar(qq); //cludge for repeats return OUTLIM; } } if(inLimFlag == 0 && isinlimit()) { inLimFlag = 1; return STARTLIM; } else if(inLimFlag == 1 && isinlimit()) { return INLIM; } else if (inLimFlag == 0 && !isinlimit()) { return OUTLIM; } else if (inLimFlag == 1 && !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, NSString *code, 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 zone int isCurrTrue(ctLimitCrit *elem) { FORALL(ctZoneVault) { if(isStringTrue(elem, [temp objectForKey: @"codeName"], [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(isStringTrue(elem, [who buff], [who coder])) return 1; } } return 0; } int checkand(NSArray *a) { int r, oldr; oldr = 1; FORALL(a) { r = 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 = checkand(temp); trslt += rslt; if(trslt) { return 1;} } ENDFORALL; 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) { int j, i; MWCHAR c; int 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]) {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; } } } }