|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License." ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* ! 25: StringTest.m by Ali Ozer ! 26: Run with -v for verbose mode (where all results, successful or not, are shown). ! 27: */ ! 28: ! 29: #ifdef TESTING ! 30: #define NXString NxString ! 31: #define NXMutableString NxMutableString ! 32: #define NXReadWriteString NxReadWriteString ! 33: #define NXReadOnlyString NxReadOnlyString ! 34: #define NXReadOnlySubstring NxReadOnlySubstring ! 35: #define NXSimpleReadOnlyString NxSimpleReadOnlyString ! 36: #define NXUniquedString NxUniquedString ! 37: #define NXGapString NxGapString ! 38: #define NXBigString NxBigString ! 39: #endif ! 40: ! 41: #import "NXString.h" ! 42: ! 43: #define TESTTESTEDSTUFF ! 44: // #define TESTGAPSTRING ! 45: // #define TESTBIGSTRING ! 46: ! 47: #ifdef TESTGAPSTRING ! 48: #import "NXGapString.h" ! 49: #endif ! 50: #ifdef TESTBIGSTRING ! 51: #import "NXBigString.h" ! 52: #endif ! 53: ! 54: #define TESTCONSTANTSTRING ! 55: ! 56: #import <stdio.h> ! 57: #import <streams/streams.h> ! 58: #import <appkit/nextstd.h> ! 59: #import <libc.h> ! 60: ! 61: #define CHARALLOC(zone, var, num) var = ((num) ? NXZoneMalloc((zone), sizeof(unichar) * (num)) : NULL) ! 62: ! 63: static int numErrors; ! 64: static BOOL verbose; ! 65: ! 66: @interface NXString (DebugStuff) ! 67: ! 68: - (void)verifyInt:(int)value :(int)desired; ! 69: - (void)verifyCStrings:(const char *)value :(const char *)desired; ! 70: - (void)verifyChars:(const char *)theRealThing; ! 71: - (void)verifyId:theRealThing; ! 72: - (void)verifyString:theRealThing; ! 73: ! 74: @end ! 75: ! 76: @implementation NXString (DebugStuff) ! 77: ! 78: static Err() ! 79: { ! 80: // Place to break on... ! 81: numErrors++; ! 82: } ! 83: ! 84: - (void)verifyChars:(const char *)theRealThing ! 85: { ! 86: unichar buffer[1000]; ! 87: BOOL equal; ! 88: ! 89: [self getCharacters:buffer]; ! 90: ! 91: if (equal = ([self length] == strlen(theRealThing))) { ! 92: int cnt, length = [self length]; ! 93: for (cnt = 0; cnt < length; cnt++) { ! 94: if (buffer[cnt] != (unichar)theRealThing[cnt]) { ! 95: equal = NO; ! 96: break; ! 97: } ! 98: } ! 99: } ! 100: ! 101: if (verbose || !equal) { ! 102: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK"); ! 103: fprintf (stderr, " %p ", self); ! 104: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 105: fprintf (stderr, "\n"); ! 106: ! 107: if (!equal) { ! 108: fprintf (stderr, "*** Should be: %s\n", theRealThing); ! 109: Err(); ! 110: } ! 111: } ! 112: } ! 113: ! 114: - (void)verifyInt:(int)value :(int)desired ! 115: { ! 116: BOOL equal = (value == desired); ! 117: ! 118: if (verbose || !equal) { ! 119: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK"); ! 120: fprintf (stderr, " %p ", self); ! 121: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 122: fprintf (stderr, "\n"); ! 123: ! 124: if (!equal) { ! 125: fprintf (stderr, "*** %d should be: %d\n", value, desired); ! 126: Err(); ! 127: } ! 128: } ! 129: } ! 130: ! 131: - (void)verifyCStrings:(const char *)value :(const char *)desired ! 132: { ! 133: BOOL equal = !strcmp(value, desired); ! 134: ! 135: if (verbose || !equal) { ! 136: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK"); ! 137: fprintf (stderr, " %p ", self); ! 138: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 139: fprintf (stderr, "\n"); ! 140: ! 141: if (!equal) { ! 142: fprintf (stderr, "*** %s should be: %s\n", value, desired); ! 143: Err(); ! 144: } ! 145: } ! 146: } ! 147: ! 148: - (void)verifyId:theRealThing ! 149: { ! 150: BOOL equal = (theRealThing == self); ! 151: ! 152: if (verbose || !equal) { ! 153: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK"); ! 154: fprintf (stderr, " %p ", self); ! 155: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 156: fprintf (stderr, "\n"); ! 157: ! 158: if (!equal) { ! 159: fprintf (stderr, "*** Should be: %p\n", theRealThing); ! 160: Err(); ! 161: } ! 162: } ! 163: } ! 164: ! 165: - (void)verifyString:theRealThing ! 166: { ! 167: BOOL equal = ([self isEqual:theRealThing]); ! 168: ! 169: if (verbose || !equal) { ! 170: fprintf (stderr, "%s:", equal ? "OK" : "*** NOT OK"); ! 171: fprintf (stderr, " %p ", self); ! 172: [self printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 173: fprintf (stderr, "\n"); ! 174: ! 175: if (!equal) { ! 176: fprintf (stderr, "*** Should be: "); ! 177: [theRealThing printForDebugger: NXOpenFile (fileno (stderr), NX_WRITEONLY)]; ! 178: fprintf (stderr, "\n"); ! 179: Err(); ! 180: } ! 181: } ! 182: } ! 183: ! 184: @end ! 185: ! 186: #define TITLE(title) \ ! 187: printf ("%s%s %s%s\n", \ ! 188: verbose ? "\n" : "", \ ! 189: [testClass name], \ ! 190: (title), \ ! 191: verbose ? ":" : "...") ! 192: ! 193: #define TITLE1(title) \ ! 194: printf ("%s%s%s\n", \ ! 195: verbose ? "\n" : "", \ ! 196: (title), \ ! 197: verbose ? ":" : "...") ! 198: ! 199: /* This function returns a string containing 200 occurences of "ab..yz" ! 200: */ ! 201: static NXString *hugeString (id testClass) ! 202: { ! 203: #define HUGESTRINGLEN 5200 ! 204: static char buf[HUGESTRINGLEN] = {'\0'}; ! 205: if (buf[0] == '\0') { ! 206: int cnt; ! 207: for (cnt = 0; cnt < HUGESTRINGLEN; cnt++) buf[cnt] = ('a' + (cnt % 26)); ! 208: } ! 209: return [[testClass alloc] initFromCString:buf]; ! 210: } ! 211: ! 212: void testBasic /* create/read/copy/free */ (id testClass) ! 213: { ! 214: id str1, str2, str3; ! 215: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 216: unichar chars2[] = {'F', 'G', 'H', 'I', 'J'}; ! 217: unichar chars3[] = {'K', 'L', 'M', 'N', 'O'}; ! 218: unichar *charPtr; ! 219: NXRange range = {1, 2}; ! 220: NXRange tmpRange = {0, 0}; ! 221: ! 222: TITLE ("basic create/read/copy/free test"); ! 223: ! 224: str1 = [[testClass alloc] initFromCharacters:chars1 length:5]; ! 225: str2 = [[testClass alloc] initFromString:str1]; ! 226: str3 = [[testClass alloc] initFromString:str2 range:range]; ! 227: [str3 verifyChars:"BC"]; ! 228: [str3 free]; ! 229: str3 = [str2 copy]; ! 230: [str3 verifyChars:"ABCDE"]; ! 231: [str2 free]; ! 232: [str3 verifyChars:"ABCDE"]; ! 233: [str3 free]; ! 234: ! 235: str3 = [[testClass alloc] initFromCharacters:chars2 length:5]; ! 236: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(range)); ! 237: [str3 getCharacters:charPtr range:range]; ! 238: str2 = [[testClass alloc] initFromCharacters:charPtr length:NX_LENGTH(range)]; ! 239: [str3 verifyChars:"FGHIJ"]; ! 240: [str2 verifyChars:"GH"]; ! 241: [str2 free]; ! 242: NX_FREE (charPtr); ! 243: ! 244: NX_LOCATION(tmpRange) = 1; ! 245: NX_LENGTH(tmpRange) = [str3 length] - 1; ! 246: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange)); ! 247: [str3 getCharacters:charPtr range:tmpRange]; ! 248: str2 = [[testClass alloc] initFromCharacters:charPtr length:NX_LENGTH(tmpRange)]; ! 249: [str2 verifyChars:"GHIJ"]; ! 250: [str2 free]; ! 251: [str3 free]; ! 252: [str1 free]; ! 253: NX_FREE (charPtr); ! 254: ! 255: str3 = [[testClass alloc] initFromCharacters:chars3 length:5]; ! 256: str2 = [str3 copy]; ! 257: NX_LOCATION(tmpRange) = 0; ! 258: NX_LENGTH(tmpRange) = [str2 length]; ! 259: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange)); ! 260: [str2 getCharacters:charPtr range:tmpRange]; ! 261: str1 = [[testClass alloc] initFromCharactersNoCopy:charPtr length:NX_LENGTH(tmpRange)]; ! 262: [str3 free]; ! 263: [str2 verifyChars:"KLMNO"]; ! 264: [str2 free]; ! 265: [str1 verifyChars:"KLMNO"]; ! 266: [str1 free]; ! 267: ! 268: str1 = [[testClass alloc] init]; ! 269: str2 = [[testClass alloc] init]; ! 270: [str1 free]; ! 271: str1 = [str2 copy]; ! 272: str3 = [[testClass alloc] initFromCharacters:NULL length:0]; ! 273: [str2 free]; ! 274: [str3 verifyChars:""]; ! 275: [str3 free]; ! 276: [str1 verifyChars:""]; ! 277: [str1 free]; ! 278: ! 279: } ! 280: ! 281: void testCopy /* copy */ (id testClass) ! 282: { ! 283: id str1, str2, str3, str4; ! 284: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 285: NXRange range = {1,3}; ! 286: ! 287: TITLE ("mutable/immutable copy test"); ! 288: ! 289: str1 = [[testClass alloc] initFromCharacters:chars1 length:5]; ! 290: str2 = [str1 mutableCopy]; ! 291: [str2 appendString:str1]; ! 292: [str2 verifyChars:"ABCDEABCDE"]; ! 293: str3 = [str1 copySubstring:range]; ! 294: str4 = [str2 copySubstring:range]; ! 295: [str4 appendString:str3]; ! 296: [str4 verifyChars:"BCDBCD"]; ! 297: [str1 free]; ! 298: [str2 free]; ! 299: str1 = [str3 mutableCopy]; ! 300: [str1 insertString:str4 at:1]; ! 301: [str1 verifyChars:"BBCDBCDCD"]; ! 302: [str3 verifyChars:"BCD"]; ! 303: [str4 verifyChars:"BCDBCD"]; ! 304: [str3 free]; ! 305: [str4 free]; ! 306: [str1 verifyChars:"BBCDBCDCD"]; ! 307: [str1 free]; ! 308: ! 309: } ! 310: ! 311: void testRefCountedAndUniqued () ! 312: { ! 313: id str1, str2, str3, str4; ! 314: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 315: NXRange range = {1,3}; ! 316: typedef struct {@defs(NXReadOnlyString);} ROString; ! 317: ! 318: TITLE1 ("NXReadOnlyString, NXReadWriteString, NXUniquedString tests"); ! 319: ! 320: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars1 length:5]; ! 321: str2 = [str1 mutableCopy]; ! 322: str3 = [str2 immutableCopy]; ! 323: [str1 verifyInt:(int)str3 :(int)str1]; ! 324: [str2 free]; ! 325: str2 = [[NXReadWriteString alloc] initFromCharacters:chars1 length:3]; ! 326: [str1 verifyInt:(int)str3 :(int)str1]; ! 327: [str1 free]; ! 328: [str3 verifyChars:"ABCDE"]; ! 329: [str2 appendString:str3]; ! 330: [str3 free]; ! 331: [str2 verifyChars:"ABCABCDE"]; ! 332: ! 333: str1 = [[NXReadOnlyString alloc] initFromCharactersNoCopy:chars1 length:5 freeWhenDone:NO]; ! 334: str2 = [str1 mutableCopy]; ! 335: str3 = [str2 immutableCopy]; ! 336: [str2 free]; ! 337: str2 = [str3 copySubstring:range]; ! 338: [str1 verifyInt:(int)(((ROString *)str1)->characters)+1 :(int)(((ROString *)str2)->characters)]; ! 339: ! 340: [str1 free]; ! 341: [str3 verifyChars:"ABCDE"]; ! 342: [str3 free]; ! 343: str3 = [str2 mutableCopy]; ! 344: [str3 insertString:str2 at:1]; ! 345: [str3 verifyChars:"BBCDCD"]; ! 346: [str3 deleteCharactersInRange:range]; ! 347: [str3 verifyChars:"BCD"]; ! 348: [str2 verifyChars:"BCD"]; ! 349: ! 350: str1 = [NXUniquedString newFromString:str3]; ! 351: str4 = [NXUniquedString newFromString:str2]; ! 352: [str1 verifyInt:(int)str4 :(int)str1]; ! 353: [str1 verifyInt:(int)[NXUniquedString newFromString:[str4 mutableCopy]] :(int)str1]; ! 354: ! 355: } ! 356: ! 357: ! 358: void testEdit /* edit */ (id testClass) ! 359: { ! 360: id str1, str2, str3; ! 361: typedef struct _NXReadWriteStringKludge { ! 362: @defs(NXReadWriteString); ! 363: } NXReadWriteStringKludge; ! 364: typedef struct _NXReadOnlyStringKludge { ! 365: @defs(NXReadOnlyString); ! 366: } NXReadOnlyStringKludge; ! 367: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 368: unichar chars2[] = {'F', 'G', 'H', 'I', 'J'}; ! 369: unichar chars3[] = {'K', 'L', 'M', 'N', 'O'}; ! 370: int addr = 0; ! 371: NXRange range = {1, 2}; ! 372: ! 373: TITLE ("appendString/delete/insertString test"); ! 374: ! 375: str1 = [[testClass alloc] initFromCharacters:chars1 length:5]; ! 376: str2 = [[testClass alloc] initFromString:str1 range:range]; ! 377: [str1 appendString:str2]; ! 378: [str1 verifyChars:"ABCDEBC"]; ! 379: [str2 verifyChars:"BC"]; ! 380: [str1 insertString:str2 at:0]; ! 381: [str1 insertString:str2 at:3]; ! 382: [str1 deleteCharactersInRange:range]; ! 383: [str1 verifyChars:"BBCBCDEBC"]; ! 384: [str1 free]; ! 385: ! 386: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars3 length:5]; ! 387: [str2 appendString:str1]; ! 388: [str1 free]; ! 389: [str2 verifyChars:"BCKLMNO"]; ! 390: if (testClass == [NXReadWriteString class]) { ! 391: addr = (int)((NXReadOnlyStringKludge *)(((NXReadWriteStringKludge *)str2)->actualString))->characters; ! 392: } ! 393: str1 = [str2 copy]; ! 394: str3 = [str1 copy]; ! 395: [str2 free]; ! 396: [str1 free]; ! 397: str2 = [str3 copy]; ! 398: [str3 verifyChars:"BCKLMNO"]; ! 399: [str2 verifyChars:"BCKLMNO"]; ! 400: if (testClass == [NXReadWriteString class]) { ! 401: [str2 verifyInt:(int)((NXReadOnlyStringKludge *)(((NXReadWriteStringKludge *)str2)->actualString))->characters :addr]; ! 402: } ! 403: str1 = [[NXReadOnlyString alloc] initFromCharacters:chars2 length:1]; ! 404: [str2 insertString:str1 at:2]; ! 405: [str1 free]; ! 406: [str3 verifyChars:"BCKLMNO"]; ! 407: [str2 verifyChars:"BCFKLMNO"]; ! 408: [str2 free]; ! 409: [str3 free]; ! 410: ! 411: str1 = [[testClass alloc] init]; ! 412: str2 = [[testClass alloc] init]; ! 413: [str1 appendString:@"Foo Bar"]; ! 414: [str1 verifyChars:"Foo Bar"]; ! 415: [str2 verifyChars:""]; ! 416: [str1 free]; ! 417: str1 = [[testClass alloc] init]; ! 418: [str2 verifyChars:""]; ! 419: [str1 appendString:str2]; ! 420: [str2 free]; ! 421: [str1 verifyChars:""]; ! 422: ! 423: } ! 424: ! 425: void testLargeEdit /* large edit */ (id testClass) ! 426: { ! 427: int cnt; ! 428: id str1, str2, str3; ! 429: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 430: NXRange range = {999, 25}; ! 431: NXRange findRange; ! 432: ! 433: TITLE ("large appendString/delete/insertString test"); ! 434: ! 435: str1 = [[testClass alloc] initFromCharacters:chars1 length:5]; ! 436: str2 = [str1 copy]; ! 437: for (cnt = 1; cnt < 64; cnt++) { ! 438: [str1 appendString:str2]; ! 439: } // Resulting length is 320 ! 440: [str2 free]; ! 441: str2 = [str1 copy]; ! 442: [str1 appendString:str2]; // 640 ! 443: [str1 appendString:str2]; // 960 ! 444: [str1 appendString:str2]; // 1280 ! 445: [str2 free]; ! 446: [str1 verifyInt:[str1 length] :1280]; ! 447: ! 448: str2 = [[testClass alloc] initFromString:str1 range:range]; ! 449: [str2 verifyChars:"EABCDEABCDEABCDEABCDEABCD"]; ! 450: [str2 insertString:str1 at:2]; ! 451: [str2 insertString:str1 at:[str2 length]]; ! 452: [str1 free]; ! 453: str3 = [str2 copySubstring:(NXRange){0, 10} fromZone:[str2 zone]]; ! 454: [str3 verifyChars:"EAABCDEABC"]; ! 455: str1 = [str2 copy]; ! 456: [str2 replaceCharactersInRange:range withString:str1]; ! 457: [str2 appendString:str3]; ! 458: [str2 appendString:@"Howdy"]; ! 459: [str3 free]; ! 460: [str2 verifyInt:[str2 length] :5160]; ! 461: findRange = [str2 findString:@"EAABCDEABCH"]; ! 462: [str2 verifyInt:NX_LOCATION(findRange) :5145]; ! 463: [str1 free]; ! 464: NX_LOCATION(range) = 2; ! 465: NX_LENGTH(range) = [str2 length] - 4; ! 466: [str2 deleteCharactersInRange:range]; ! 467: [str2 verifyChars:"EAdy"]; ! 468: [str2 free]; ! 469: } ! 470: ! 471: void testCompare /* compare */ (id testClass) ! 472: { ! 473: id str1, str2, str3, str4, str5; ! 474: unichar chars1[] = {'A', 'B', 'C', 'D', 'E'}; ! 475: unichar chars2[] = {'F', 'G', 'h', 'f', 'g'}; ! 476: unichar chars3[] = {'F', 'g', 'H', 'f', 'G'}; ! 477: ! 478: TITLE ("compare test"); ! 479: ! 480: str1 = [[testClass alloc] initFromCharacters:chars1 length:5]; ! 481: str2 = [[testClass alloc] initFromCharacters:chars1 length:4]; ! 482: str3 = [[testClass alloc] initFromCharacters:chars2 length:4]; ! 483: [str1 verifyInt:[str1 compare:str1] :0]; ! 484: [str1 verifyInt:[str1 compare:str2] :1]; ! 485: [str1 verifyInt:[str1 compare:str3] :-1]; ! 486: [str2 verifyInt:[str2 compare:str1] :-1]; ! 487: [str2 verifyInt:[str2 compare:str3] :-1]; ! 488: [str3 verifyInt:[str3 compare:str1] :1]; ! 489: [str3 verifyInt:[str3 compare:str2] :1]; ! 490: str4 = [[NXReadWriteString alloc] initFromString:str1]; ! 491: str5 = [str4 copy]; ! 492: [str1 verifyInt:[str1 compare:str4] :0]; ! 493: [str5 verifyInt:[str5 compare:str1] :0]; ! 494: [str4 appendString:str4]; ! 495: [str1 verifyInt:[str1 compare:str4] :-1]; ! 496: [str5 verifyInt:[str5 compare:str1] :0]; ! 497: [str4 free]; ! 498: [str5 free]; ! 499: [str1 free]; ! 500: [str2 free]; ! 501: str4 = [[testClass alloc] initFromCharacters:chars3 length:4]; ! 502: [str4 verifyInt:[str4 compare:str3] :1]; ! 503: [str3 verifyInt:[str3 compare:str4] :-1]; ! 504: [str4 verifyInt:[str4 compare:str3 mask:NX_CASE_INSENSITIVE table:NULL] :0]; ! 505: [str3 verifyInt:[str3 compare:str4 mask:NX_CASE_INSENSITIVE table:NULL] :0]; ! 506: str2 = [[NXReadOnlyString alloc] initFromString:str3]; ! 507: [str4 verifyInt:[str4 compare:str2] :1]; ! 508: [str2 verifyInt:[str2 compare:str4] :-1]; ! 509: [str2 free]; ! 510: [str3 free]; ! 511: [str4 free]; ! 512: } ! 513: ! 514: #define wholeRange(s) ((NXRange){0, [(s) length]}) ! 515: ! 516: void testFind /* find */ (id testClass) ! 517: { ! 518: id str1, str2, str3, str4; ! 519: unichar chars1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'g', 'h', 'a', 'b', 'B', 'C'}; ! 520: unichar chars2[] = {'F', 'G', 'h', 'f', 'g'}; ! 521: unichar chars3[] = {'F', 'g', 'H', 'f', 'G'}; ! 522: NXRange findRange; ! 523: ! 524: TITLE ("find test"); ! 525: ! 526: str1 = [[testClass alloc] initFromCharacters:chars1 length:12]; // ABCDEFghabBC ! 527: str2 = [[testClass alloc] initFromCharacters:chars1 length:2]; // AB ! 528: str3 = [[testClass alloc] initFromCharacters:chars2 length:2]; // FG ! 529: str4 = [[testClass alloc] initFromCharacters:chars3 length:2]; // Fg ! 530: ! 531: findRange = [str1 findString:str2]; ! 532: [str1 verifyInt:NX_LOCATION(findRange) :0]; ! 533: [str1 verifyInt:NX_LENGTH(findRange) :2]; ! 534: findRange = [str1 findString:str3]; ! 535: [str1 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND]; ! 536: [str1 verifyInt:NX_LENGTH(findRange) :0]; ! 537: findRange = [str1 findString:str4]; ! 538: [str1 verifyInt:NX_LOCATION(findRange) :5]; ! 539: [str1 verifyInt:NX_LENGTH(findRange) :2]; ! 540: findRange = [str1 findString:str3 range:wholeRange(str1) mask:NX_CASE_INSENSITIVE table:NULL]; ! 541: [str1 verifyInt:NX_LOCATION(findRange) :5]; ! 542: [str1 verifyInt:NX_LENGTH(findRange) :2]; ! 543: findRange = [str1 findString:str2 range:wholeRange(str1) mask:NX_CASE_INSENSITIVE|NX_BACKWARDS_SEARCH table:NULL]; ! 544: [str1 verifyInt:NX_LOCATION(findRange) :8]; ! 545: [str1 verifyInt:NX_LENGTH(findRange) :2]; ! 546: findRange = [str1 findString:str2 range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL]; ! 547: [str1 verifyInt:NX_LOCATION(findRange) :0]; ! 548: [str1 verifyInt:NX_LENGTH(findRange) :2]; ! 549: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_BACKWARDS_SEARCH table:NULL]; ! 550: [str3 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND]; ! 551: [str3 verifyInt:NX_LENGTH(findRange) :0]; ! 552: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_CASE_INSENSITIVE|NX_BACKWARDS_SEARCH table:NULL]; ! 553: [str3 verifyInt:NX_LOCATION(findRange) :0]; ! 554: [str3 verifyInt:NX_LENGTH(findRange) :2]; ! 555: findRange = [str3 findString:str4 range:wholeRange(str3) mask:NX_CASE_INSENSITIVE table:NULL]; ! 556: [str3 verifyInt:NX_LOCATION(findRange) :0]; ! 557: [str3 verifyInt:NX_LENGTH(findRange) :2]; ! 558: findRange = [str2 findString:str1]; ! 559: [str2 verifyInt:NX_LOCATION(findRange) :NX_STRING_NOT_FOUND]; ! 560: [str2 verifyInt:NX_LENGTH(findRange) :0]; ! 561: ! 562: NX_LOCATION(findRange) = 1; ! 563: NX_LENGTH(findRange) = [str1 length] - 1; ! 564: findRange = [str1 findString:str2 range:findRange mask:NX_CASE_INSENSITIVE table:NULL]; ! 565: [str3 verifyInt:NX_LOCATION(findRange) :8]; ! 566: [str3 verifyInt:NX_LENGTH(findRange) :2]; ! 567: ! 568: } ! 569: ! 570: void testStream (id testClass) ! 571: { ! 572: const char *bytes = "Hello There. Hi There."; ! 573: unichar chars1[] = {'A', 'B', 'C', 0, 1, 2, '0', '1', '2'}; ! 574: NXStream *stream; ! 575: id str1, str2, str3, str4; ! 576: NXCharacterSet *numberSet; ! 577: ! 578: TITLE ("stream test"); ! 579: ! 580: numberSet = [[NXCharacterSet alloc] init]; ! 581: [numberSet addRange:'0' :'9']; ! 582: ! 583: stream = NXOpenMemory(bytes, strlen(bytes), NX_READONLY); ! 584: str1 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:1]; ! 585: str2 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:17]; ! 586: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:120]; ! 587: ! 588: [str1 verifyChars:"H"]; ! 589: [str2 verifyChars:"ello There. Hi Th"]; ! 590: [str3 verifyChars:"ere."]; ! 591: [str1 free]; ! 592: [str3 free]; ! 593: ! 594: NXClose (stream); ! 595: ! 596: stream = NXOpenMemory(NULL, 0, NX_READWRITE); ! 597: [str2 writeCStringToStream:stream]; ! 598: str1 = [[testClass alloc] initFromCharacters:chars1 length:9]; ! 599: [str1 writeCStringToStream:stream]; ! 600: ! 601: NXSeek(stream, 1, NX_FROMSTART); ! 602: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH]; ! 603: ! 604: str4 = [[NXReadWriteString alloc] init]; ! 605: [str4 append:str2]; ! 606: [str4 deleteCharactersInRange:(NXRange){0,1}]; // Because we seeked to 1 above... ! 607: [str4 append:str1]; ! 608: ! 609: [str3 verifyString:str4]; ! 610: [str3 verifyInt:[str3 length] :[str2 length] - 1 + 9]; ! 611: ! 612: [str3 free]; ! 613: ! 614: NXSeek(stream, 1, NX_FROMSTART); ! 615: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:numberSet maxLength:NX_MAX_STRING_LENGTH]; ! 616: ! 617: [str4 deleteCharactersInRange:(NXRange){[str4 length]-3, 3}]; ! 618: [str3 verifyString:str4]; ! 619: [str3 verifyInt:[str3 length] :[str2 length] - 1 + 6]; ! 620: [str3 free]; ! 621: ! 622: NXSeek(stream, 1, NX_FROMSTART); ! 623: str3 = [[testClass alloc] initFromCStringStream:stream untilOneOf:numberSet maxLength:5]; ! 624: ! 625: [str4 deleteCharactersInRange:(NXRange){5, [str4 length] - 5}]; ! 626: [str3 verifyString:str4]; ! 627: [str3 verifyInt:[str3 length] :5]; ! 628: [str3 free]; ! 629: ! 630: [str1 free]; ! 631: [str2 free]; ! 632: [str4 free]; ! 633: ! 634: NXCloseMemory(stream, NX_FREEBUFFER); ! 635: ! 636: str1 = hugeString(testClass); ! 637: ! 638: stream = NXOpenMemory(NULL, 0, NX_READWRITE); ! 639: [str1 writeCStringToStream:stream]; ! 640: NXSeek(stream, 0, NX_FROMSTART); ! 641: str2 = [[testClass alloc] initFromCStringStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH]; ! 642: [str1 verifyString:str2]; ! 643: [str2 free]; ! 644: NXCloseMemory(stream, NX_FREEBUFFER); ! 645: ! 646: stream = NXOpenMemory(NULL, 0, NX_READWRITE); ! 647: [str1 writeToStream:stream]; ! 648: NXSeek(stream, 0, NX_FROMSTART); ! 649: str2 = [[testClass alloc] initFromStream:stream untilOneOf:nil maxLength:NX_MAX_STRING_LENGTH]; ! 650: [str1 verifyString:str2]; ! 651: [str2 free]; ! 652: NXCloseMemory(stream, NX_FREEBUFFER); ! 653: ! 654: [str1 free]; ! 655: } ! 656: ! 657: void testHash (id testClass) ! 658: { ! 659: id str1; ! 660: unichar chars1[] = {'F', 'o', 'o'}; ! 661: ! 662: TITLE ("hash test"); ! 663: ! 664: str1 = [[testClass alloc] initFromCharacters:chars1 length:3]; ! 665: [str1 verifyInt:[str1 hash] :32095]; ! 666: [str1 verifyInt:[str1 hash] :[@"Foo" hash]]; ! 667: [str1 free]; ! 668: ! 669: str1 = [[testClass alloc] initFromString:@"Hello World"]; ! 670: [str1 verifyInt:[str1 hash] :850486630]; ! 671: [str1 free]; ! 672: } ! 673: ! 674: void testFormat (id testClass) ! 675: { ! 676: id str1, str2, str3; ! 677: int cnt; ! 678: unichar chars1[] = {'F', 'o', 'o'}; ! 679: ! 680: TITLE ("formatted create test"); ! 681: ! 682: str1 = [[NXReadOnlyString alloc] initFromCString:"===%2.1f %d %s %@==="]; ! 683: str2 = [[NXReadOnlyString alloc] initFromCharacters:chars1 length:3]; ! 684: str3 = [[testClass alloc] initFromFormat:str1, 3.14, -42, "Hello World", str2]; ! 685: ! 686: [str3 verifyChars:"===3.1 -42 Hello World Foo==="]; ! 687: ! 688: [str1 free]; ! 689: [str2 free]; ! 690: [str3 free]; ! 691: ! 692: str1 = [[NXReadOnlyString alloc] initFromCString:"Hello"]; ! 693: str3 = [[NXReadWriteString alloc] initFromString:str1]; ! 694: for (cnt = 0; cnt < 12; cnt++) { ! 695: str2 = [[testClass alloc] initFromFormat:@"%@*%@", str1, str1]; ! 696: [str3 appendString:@"*"]; // Test string; we assume append works. ! 697: [str3 appendString:str1]; ! 698: [str2 verifyString:str3]; ! 699: [str1 free]; ! 700: str1 = str2; ! 701: } ! 702: [str3 free]; ! 703: str3 = [[NXReadOnlyString alloc] initFromString:str1 range:(NXRange){[str1 length] - 6, 6}]; ! 704: [str3 verifyChars:"*Hello"]; ! 705: [str1 free]; ! 706: [str3 free]; ! 707: } ! 708: ! 709: void testCStrings (id testClass) ! 710: { ! 711: id str1, str2; ! 712: char *cString; ! 713: NXAtom uString1, uString2; ! 714: #define CSTRBUFLEN 10 ! 715: #define CSTRBIGBUFLEN 1000 ! 716: char cStringBuffer[CSTRBIGBUFLEN+1]; ! 717: int cnt; ! 718: NXRange range; ! 719: ! 720: TITLE ("CString test"); ! 721: ! 722: str1 = [[NXReadOnlyString alloc] initFromCString:"Hello World"]; ! 723: str2 = [str1 mutableCopy]; ! 724: cString = [str1 cStringCopy]; ! 725: [str1 verifyChars:cString]; ! 726: free (cString); ! 727: uString1 = [str1 uniqueCStringCopy]; ! 728: [str1 verifyChars:uString1]; ! 729: uString2 = [str1 uniqueCStringCopy]; ! 730: [str1 verifyInt:(int)uString1 :(int)uString2]; ! 731: uString2 = [str2 uniqueCStringCopy]; ! 732: [str1 verifyInt:(int)uString1 :(int)uString2]; ! 733: [str2 appendString:@""]; ! 734: uString2 = [str2 uniqueCStringCopy]; ! 735: [str1 verifyInt:(int)uString1 :(int)uString2]; ! 736: [str2 appendString:@" "]; ! 737: uString1 = [str2 uniqueCStringCopy]; ! 738: uString2 = [@"Hello World " uniqueCStringCopy]; ! 739: [str2 verifyInt:(int)uString1 :(int)uString2]; ! 740: [str1 free]; ! 741: [str2 free]; ! 742: ! 743: str1 = [[testClass alloc] initFromCString:"Bonjour Everyone"]; ! 744: [str1 getCString:cStringBuffer maxLength:3]; ! 745: [str1 verifyCStrings:cStringBuffer :"Bon"]; ! 746: [str1 getCString:cStringBuffer maxLength:0]; ! 747: [str1 verifyCStrings:cStringBuffer :""]; ! 748: NX_LOCATION(range) = 8; NX_LENGTH(range) = 5; ! 749: [str1 getCString:cStringBuffer maxLength:NX_MAX_STRING_LENGTH range:range remainingRange:NULL]; ! 750: [str1 verifyCStrings:cStringBuffer :"Every"]; ! 751: [str1 getCString:cStringBuffer maxLength:2 range:range remainingRange:NULL]; ! 752: [str1 verifyCStrings:cStringBuffer :"Ev"]; ! 753: [str1 getCString:cStringBuffer maxLength:CSTRBUFLEN range:range remainingRange:NULL]; ! 754: [str1 verifyCStrings:cStringBuffer :"Every"]; ! 755: [str1 getCString:cStringBuffer maxLength:CSTRBUFLEN]; ! 756: [str1 verifyCStrings:cStringBuffer :"Bonjour Ev"]; ! 757: NX_LOCATION(range) = 0; ! 758: NX_LENGTH(range) = 11; ! 759: [str1 getCString:cStringBuffer maxLength:0 range:range remainingRange:&range]; ! 760: [str1 verifyCStrings:cStringBuffer :""]; ! 761: [str1 verifyInt:NX_LOCATION(range) :0]; ! 762: [str1 verifyInt:NX_LENGTH(range) :11]; ! 763: [str1 getCString:cStringBuffer maxLength:5 range:range remainingRange:&range]; ! 764: [str1 verifyCStrings:cStringBuffer :"Bonjo"]; ! 765: [str1 verifyInt:NX_LOCATION(range) :5]; ! 766: [str1 verifyInt:NX_LENGTH(range) :6]; ! 767: [str1 getCString:cStringBuffer maxLength:10 range:range remainingRange:&range]; ! 768: [str1 verifyCStrings:cStringBuffer :"ur Eve"]; ! 769: [str1 verifyInt:NX_LOCATION(range) :11]; ! 770: [str1 verifyInt:NX_LENGTH(range) :0]; ! 771: [str1 free]; ! 772: ! 773: str1 = hugeString(testClass); ! 774: [str1 getCString:cStringBuffer maxLength:CSTRBIGBUFLEN range:(NXRange){0,[str1 length]} remainingRange:&range]; ! 775: cnt = 26 * ((int)(CSTRBIGBUFLEN / 26) - 1); ! 776: cStringBuffer[cnt + 26] = '\0'; ! 777: [str1 verifyCStrings:&cStringBuffer[cnt] :"abcdefghijklmnopqrstuvwxyz"]; ! 778: [str1 verifyInt:NX_LOCATION(range) :CSTRBIGBUFLEN]; ! 779: [str1 verifyInt:NX_LENGTH(range) :[str1 length] - CSTRBIGBUFLEN]; ! 780: [str1 free]; ! 781: } ! 782: ! 783: void testFindAndSets (id testClass) ! 784: { ! 785: id str1; ! 786: unichar chars1[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '1', 'h', '3'}; ! 787: unichar chars2[] = {' ', '\t'}; ! 788: NXCharacterSet *numberSet, *alphaSet, *spaceSet, *notAlphaSet, *numAndAlphaSet; ! 789: ! 790: TITLE ("find and NXCharacterSet test"); ! 791: ! 792: numberSet = [[NXCharacterSet alloc] init]; ! 793: [numberSet addRange:'0' :'9']; ! 794: ! 795: alphaSet = [[NXCharacterSet alloc] init]; ! 796: [alphaSet addRange:'a' :'z']; ! 797: [alphaSet addRange:'A' :'Z']; ! 798: ! 799: notAlphaSet = [[NXCharacterSet alloc] init]; ! 800: [notAlphaSet addRange:'a' :'z']; ! 801: [notAlphaSet addRange:'A' :'Z']; ! 802: [notAlphaSet invert]; ! 803: ! 804: spaceSet = [[NXCharacterSet alloc] init]; ! 805: [spaceSet addCharacters:chars2 length:2]; ! 806: [spaceSet addCharacters:chars1 length:14]; ! 807: [spaceSet removeCharacters:chars1 length:14]; ! 808: [spaceSet addCharacters:chars2 length:2]; ! 809: ! 810: numAndAlphaSet = [[NXCharacterSet alloc] init]; ! 811: [numAndAlphaSet unionWith:alphaSet]; ! 812: [numAndAlphaSet unionWith:numberSet]; ! 813: ! 814: str1 = [[testClass alloc] initFromCharacters:chars1 length:14]; ! 815: [str1 verifyInt:[str1 findCharacter:'l'] :2]; ! 816: [str1 verifyInt:[str1 findCharacter:'l' range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :9]; ! 817: [str1 verifyInt:[str1 findCharacter:'h' range:wholeRange(str1) mask:NX_CASE_INSENSITIVE table:NULL] :0]; ! 818: [str1 verifyInt:[str1 findCharacter:'h' range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :12]; ! 819: ! 820: [str1 verifyInt:[str1 findOneOf:alphaSet] :0]; ! 821: [str1 verifyInt:[str1 findOneOf:notAlphaSet] :5]; ! 822: [str1 verifyInt:[str1 findOneOf:spaceSet] :5]; ! 823: [str1 verifyInt:[str1 findOneOf:numberSet] :11]; ! 824: [str1 verifyInt:[str1 findOneOf:numberSet range:wholeRange(str1) mask:NX_BACKWARDS_SEARCH table:NULL] :13]; ! 825: } ! 826: ! 827: #ifdef TESTCONSTANTSTRING ! 828: void testConstant /* basic constant string functionality */ () ! 829: { ! 830: id str1, str2, str3; ! 831: unichar *charPtr; ! 832: NXRange range = {1, 2}; ! 833: NXRange tmpRange = {0, 0}; ! 834: ! 835: TITLE1 ("NXConstantString test"); ! 836: ! 837: str1 = [[NXReadOnlyString alloc] initFromString:@"ABCDE"]; ! 838: str2 = [[NXReadOnlyString alloc] initFromString:str1]; ! 839: str3 = [[NXReadOnlyString alloc] initFromString:str2 range:range]; ! 840: [str3 verifyChars:"BC"]; ! 841: [str3 free]; ! 842: str3 = [str2 copy]; ! 843: [str3 verifyChars:"ABCDE"]; ! 844: [str2 free]; ! 845: [str3 verifyChars:"ABCDE"]; ! 846: [str3 free]; ! 847: ! 848: str3 = [[NXReadOnlyString alloc] initFromString:@"FGHIJ"]; ! 849: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(range)); ! 850: [str3 getCharacters:charPtr range:range]; ! 851: str2 = [[NXReadOnlyString alloc] initFromCharacters:charPtr length:NX_LENGTH(range)]; ! 852: [str3 verifyChars:"FGHIJ"]; ! 853: [str2 verifyChars:"GH"]; ! 854: [str2 free]; ! 855: NX_FREE (charPtr); ! 856: ! 857: NX_LOCATION(tmpRange) = 1; ! 858: NX_LENGTH(tmpRange) = [str3 length] - 1; ! 859: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange)); ! 860: [str3 getCharacters:charPtr range:tmpRange]; ! 861: str2 = [[NXReadOnlyString alloc] initFromCharacters:charPtr length:NX_LENGTH(tmpRange)]; ! 862: [str2 verifyChars:"GHIJ"]; ! 863: [str2 free]; ! 864: [str3 free]; ! 865: [str1 free]; ! 866: NX_FREE (charPtr); ! 867: ! 868: str3 = [[NXReadOnlyString alloc] initFromString:@"KLM" @"NO"]; ! 869: str2 = [str3 copy]; ! 870: NX_LOCATION(tmpRange) = 0; ! 871: NX_LENGTH(tmpRange) = [str2 length]; ! 872: CHARALLOC(NXDefaultMallocZone(), charPtr, NX_LENGTH(tmpRange)); ! 873: [str2 getCharacters:charPtr range:tmpRange]; ! 874: str1 = [[NXReadOnlyString alloc] initFromCharactersNoCopy:charPtr length:NX_LENGTH(tmpRange)]; ! 875: [str3 free]; ! 876: [str2 verifyChars:"KLMNO"]; ! 877: [str2 free]; ! 878: [str1 verifyChars:"KLMNO"]; ! 879: [str1 free]; ! 880: ! 881: str1 = [[NXReadWriteString alloc] init]; ! 882: str2 = [str1 copy]; ! 883: [str1 appendString:@"Foo"]; ! 884: [str1 verifyInt:[str1 isEqual:@""] :NO]; ! 885: [str2 verifyInt:[str2 isEqual:@""] :YES]; ! 886: [str1 free]; ! 887: [str2 verifyInt:[str2 isEqual:@""] :YES]; ! 888: [str2 free]; ! 889: } ! 890: ! 891: ! 892: #endif ! 893: ! 894: void main (int argc, char **argv) ! 895: { ! 896: numErrors = 0; ! 897: verbose = (argc > 1) && (strcmp(argv[1], "-v") == 0); ! 898: ! 899: #ifdef TESTTESTEDSTUFF ! 900: testBasic ([NXReadOnlyString class]); ! 901: testBasic ([NXReadWriteString class]); ! 902: testBasic ([NXUniquedString class]); ! 903: testBasic ([NXSimpleReadOnlyString class]); ! 904: ! 905: testCopy ([NXReadOnlyString class]); ! 906: testCopy ([NXReadWriteString class]); ! 907: testCopy ([NXUniquedString class]); ! 908: testCopy ([NXSimpleReadOnlyString class]); ! 909: ! 910: testRefCountedAndUniqued (); ! 911: ! 912: testEdit ([NXReadWriteString class]); ! 913: testLargeEdit ([NXReadWriteString class]); ! 914: ! 915: testCompare ([NXReadOnlyString class]); ! 916: testCompare ([NXReadWriteString class]); ! 917: testCompare ([NXUniquedString class]); ! 918: testCompare ([NXSimpleReadOnlyString class]); ! 919: ! 920: testFind ([NXReadOnlyString class]); ! 921: testFind ([NXReadWriteString class]); ! 922: testFind ([NXUniquedString class]); ! 923: testFind ([NXSimpleReadOnlyString class]); ! 924: ! 925: testStream ([NXReadOnlyString class]); ! 926: testStream ([NXReadWriteString class]); ! 927: testStream ([NXUniquedString class]); ! 928: testStream ([NXSimpleReadOnlyString class]); ! 929: ! 930: testFormat ([NXReadOnlyString class]); ! 931: testFormat ([NXReadWriteString class]); ! 932: testFormat ([NXUniquedString class]); ! 933: testFormat ([NXSimpleReadOnlyString class]); ! 934: ! 935: testFindAndSets ([NXReadOnlyString class]); ! 936: testFindAndSets ([NXReadWriteString class]); ! 937: testFindAndSets ([NXUniquedString class]); ! 938: testFindAndSets ([NXSimpleReadOnlyString class]); ! 939: ! 940: testCStrings ([NXReadOnlyString class]); ! 941: testCStrings ([NXReadWriteString class]); ! 942: testCStrings ([NXUniquedString class]); ! 943: testCStrings ([NXSimpleReadOnlyString class]); ! 944: ! 945: testHash ([NXReadOnlyString class]); ! 946: testHash ([NXReadWriteString class]); ! 947: testHash ([NXUniquedString class]); ! 948: testHash ([NXSimpleReadOnlyString class]); ! 949: #endif ! 950: ! 951: #ifdef TESTGAPSTRING ! 952: testBasic ([NXGapString class]); ! 953: testCopy ([NXGapString class]); ! 954: testEdit ([NXGapString class]); ! 955: testCompare ([NXGapString class]); ! 956: testFind ([NXGapString class]); ! 957: testLargeEdit ([NXGapString class]); ! 958: testStream ([NXGapString class]); ! 959: testFormat ([NXGapString class]); ! 960: testFindAndSets ([NXGapString class]); ! 961: testCStrings ([NXGapString class]); ! 962: testHash ([NXGapString class]); ! 963: #endif ! 964: ! 965: #ifdef TESTBIGSTRING ! 966: testBasic ([NXBigString class]); ! 967: testCopy ([NXBigString class]); ! 968: testEdit ([NXBigString class]); ! 969: testCompare ([NXBigString class]); ! 970: testFind ([NXBigString class]); ! 971: testLargeEdit ([NXBigString class]); ! 972: testStream ([NXBigString class]); ! 973: testFormat ([NXBigString class]); ! 974: testFindAndSets ([NXBigString class]); ! 975: testCStrings ([NXBigString class]); ! 976: testHash ([NXBigString class]); ! 977: #endif ! 978: ! 979: #ifdef TESTCONSTANTSTRING ! 980: testConstant(); ! 981: #endif ! 982: ! 983: fprintf (stderr, "\n%s%d error%s.\n", numErrors ? "*** " : "", numErrors, numErrors == 1 ? "" : "s"); ! 984: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.