1 /*
2 This product contains certain software code or other information
3 ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). The AT&T
4 Software is provided to you "AS IS". YOU ASSUME TOTAL RESPONSIBILITY
5 AND RISK FOR USE OF THE AT&T SOFTWARE. AT&T DOES NOT MAKE, AND
6 EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
7 WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
8 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
9 TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
10 WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
11 PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
12 WILL MEET YOUR REQUIREMENTS.
13
14 Unless you accept a license to use the AT&T Software, you shall not
15 reverse compile, disassemble or otherwise reverse engineer this
16 product to ascertain the source code for any AT&T Software.
17
18 (c) AT&T Corp. All rights reserved. AT&T is a registered trademark of AT&T Corp.
19
20 ***********************************************************************
21
22 Description:
23
24 Program to test the in-memory API to the XMill (de)compression routines
25
26 History:
27
28 10/11/2002 - created by Hedzer Westra <hedzer@adlibsoft.com>
29
30 */
31
32 #include "stdafx.h"
33
34 #define MAXEXPRS 1024
35
36 #ifdef _DEBUG
37 /* undefine to skip storing of XMI files */
38 #define SAVE_OUTPUT
39 #endif
40
41 /* global err msg */
42 char *errstr = NULL;
43
44 /* compress and decompress 'buffer' using type 'lossy',
45 * save it to 'filename'.xmi and 'filename'.xml
46 * and then check consistency with the original XML iff
47 * compression was lossless.
48 */
compdecomp(char * buffer,int buflen,char * filename,int targetsize,clock_t * t2t,clock_t * t3t,int * xmibuflenp,bool isFirst)49 int testsettings::compdecomp(char *buffer, int buflen, char *filename, int targetsize,
50 clock_t *t2t, clock_t *t3t, int *xmibuflenp, bool isFirst)
51 {
52 char *xmibuf = NULL;
53 char *xmlbuf = NULL;
54 int xmibuflen = 0, xmlbuflen = 0;
55 char *compr = NULL;
56 #ifdef SAVE_OUTPUT
57 char dumstr[BUFLEN];
58 #endif
59 clock_t t1 = clock();
60 int stat = 0, cstat = 0;
61 clock_t t2, t3;
62 int bytesread = 0, endmarker = 0, len = 0;
63
64 try {
65 /* compress */
66 if (blocksize > 0) {
67 /* read XML data per block */
68
69 /* init */
70 xmill->InitCompress(&xmibuf, &xmibuflen, &bytesread);
71 do {
72 /* must we signal end-of-data ? */
73 if ((len = min(blocksize, buflen-bytesread)) == buflen-bytesread) {
74 endmarker = XMILL_END_DATA;
75 } else {
76 endmarker = XMILL_END_NONE;
77 }
78 /* compress this block */
79 xmill->CompressBlock(
80 &buffer[bytesread],
81 len,
82 &endmarker);
83 } while (bytesread < buflen);
84 /* check endmarker */
85 if (endmarker != XMILL_END_DATA) {
86 /* XML file not valid! */
87 //throw new XMillException(XMILL_ERR_PARSE, "There are unclosed XML tags!");
88 stat = XMILL_ERR_PARSE;
89 goto cleanup;
90 }
91 /* end the compression */
92 xmill->EndCompress();
93 } else {
94 /* compress a whole XML file at once */
95 xmill->Compress(buffer, buflen, &xmibuf, &xmibuflen, &bytesread);
96 }
97 } catch (XMillException *e) {
98 stat = e->code;
99 errstr = str_save(e->GetErrorMsg());
100 delete e;
101 t3 = t2 = clock();
102 goto cleanup;
103 }
104
105 t2 = clock();
106
107 #ifdef SAVE_OUTPUT
108 /* write to file */
109 if (filename) {
110 sprintf(dumstr, "%s.%s", filename, XMILL_EXT_XMI);
111 FILE *f1 = fopen(dumstr, "wb");
112 if (f1) {
113 fwrite(xmibuf, 1, xmibuflen, f1);
114 fclose(f1);
115 }
116 }
117 #endif
118
119 try {
120 /* decompress */
121 if (blocksize > 0) {
122 /* read XMI data per block */
123
124 /* init */
125 xmill->InitDecompress(&xmlbuf, &xmlbuflen, &bytesread);
126 do {
127 /* decompress this block */
128 xmill->DecompressBlock(
129 &xmibuf[bytesread],
130 min(blocksize, xmibuflen-bytesread),
131 &endmarker);
132 } while (bytesread < xmibuflen);
133 /* check endmarker */
134 if (endmarker != XMILL_END_DATA) {
135 /* XMI file not valid! */
136 stat = XMILL_ERR_PARSE;
137 goto cleanup;
138 }
139 /* end the decompression */
140 xmill->EndDecompress();
141 } else {
142 /* decompress in one go */
143 xmill->Decompress(xmibuf, xmibuflen,
144 &xmlbuf, &xmlbuflen, &bytesread);
145 }
146 } catch (XMillException *e) {
147 stat = e->code;
148 errstr = str_save(e->GetErrorMsg());
149 delete e;
150 t3 = clock();
151 goto cleanup;
152 }
153
154 /* get timings */
155 t3 = clock();
156 t3 -= t2;
157 t2 -= t1;
158 *t2t += t2;
159 *t3t += t3;
160
161 *xmibuflenp = xmibuflen;
162
163 /* free XMI data */
164 free (xmibuf);
165
166 /* check targetsize */
167 if ( targetsize > 0
168 && targetsize != xmibuflen
169 && stats >= TEST_STATS_ERR) {
170 if (!mustfail) {
171 printf("Targetsize not matched!\n");
172 }
173 stat = TEST_ERROR_TARGETSIZE;
174 }
175
176 #ifdef SAVE_OUTPUT
177 /* write output to file */
178 if (filename) {
179 sprintf(dumstr, "%s.xml", filename);
180 FILE *f1 = fopen(dumstr, "wb");
181 if (f1) {
182 fwrite(xmlbuf, xmlbuflen, 1, f1);
183 fclose(f1);
184 }
185 }
186 #endif
187
188 cstat = checkintegrity(buffer, buflen, xmlbuf, xmlbuflen);
189 if (stat == 0) {
190 stat = cstat;
191 }
192
193 cleanup:
194 /* print stats */
195 switch (bzip) {
196 case XMILL_GPC_BZIP:
197 compr = "bzip2";
198 break;
199 case XMILL_GPC_GZIP:
200 compr = "gzip";
201 break;
202 case XMILL_GPC_NONE:
203 compr = "nozip";
204 break;
205 case XMILL_GPC_PPMDI:
206 compr = "ppmdi";
207 break;
208 default:
209 compr = "unknown";
210 break;
211 }
212 if ( (stats >= TEST_STATS_BPCTIME && isFirst)
213 || (stat != 0 && stats >= TEST_STATS_ERR && !mustfail)) {
214 /* print stats */
215 printf ("stats:\txml: %ld Bytes, xmi: %ld Bytes, target: %ld Bytes\n"
216 "\tratio: %6.2lf%%, bpc: %4.2lf\n"
217 "\ttype: %s, compressor: %s, idx: %ld, paths: %s\n",
218 buflen, xmibuflen, targetsize,
219 (double)xmibuflen * 100 / (double)buflen,
220 (double)xmibuflen * 8 / (double)buflen,
221 lossy ? "lossy" : "lossless",
222 compr, gpcidx,
223 exprs ? "yes" : "no");
224 }
225
226 /* free decompressed XML data */
227 tryfree (xmlbuf);
228
229 return stat;
230 }
231
checkintegrity(char * buffer,int buflen,char * xmlbuf,int xmlbuflen)232 int testsettings::checkintegrity(char *buffer, int buflen, char *xmlbuf, int xmlbuflen)
233 {
234 int i = 0, j = 0, stat = 0;
235 bool different = false;
236
237 /* check that input==output */
238 if (ignorewhite || lossy) {
239 /* text should be the same except whitespace */
240 while(i < buflen && j < xmlbuflen) {
241 while (isspace(buffer[i])) i++;
242 while (isspace(xmlbuf[j])) j++;
243 if (buffer[i] != xmlbuf[j]) {
244 different = true;
245 break;
246 }
247 i++;
248 j++;
249 }
250 if (different) {
251 if (stats >= TEST_STATS_ERR && !mustfail) {
252 printf("uncompressed data differs in pos %ld/%ld! ('%c' != '%c')\n",
253 i, j, buffer[i], xmlbuf[j]);
254 }
255 stat = TEST_ERROR_NOIGNMATCH;
256 }
257 } else {
258 /* text should be exactly the same */
259 if ( buflen != xmlbuflen
260 && stats >= TEST_STATS_ERR
261 && !mustfail) {
262 printf("uncompressed data size differs: %ld != %ld!\n", buflen, xmlbuflen);
263 }
264 int thebuflen = min(xmlbuflen, buflen);
265 if (memcmp(buffer, xmlbuf, thebuflen)) {
266 while(i < thebuflen && buffer[i]==xmlbuf[i]) i++;
267 stat = TEST_ERROR_NOEXACTMATCH;
268 if (stats >= TEST_STATS_ERR && !mustfail) {
269 printf("uncompressed data differs in pos %ld! ('%c' != '%c')\n",
270 i, buffer[i], xmlbuf[i]);
271 }
272 }
273 }
274
275 cleanup:
276 return stat;
277 }
278
279 /* decompress the xmifile and check consistency with xmlfile */
rundecomp(char * xmlfile,char * xmifile,int times)280 int testsettings::rundecomp(char *xmlfile, char *xmifile, int times)
281 {
282 int stat = 0, i = 0;
283 char *xmlbuf = NULL;
284 char *xmibuf = NULL;
285 char *xmlbuf2 = NULL;
286 int xmlbuflen = 0;
287 int xmibuflen = 0;
288 int xmlbuflen2 = 0;
289 clock_t t1, t2;
290 int bytesread = 0;
291
292 /* read XML and XMI file */
293 if ((stat = readfile(xmlfile, &xmlbuf, &xmlbuflen)) != 0) {
294 goto cleanup;
295 }
296 if ((stat = readfile(xmifile, &xmibuf, &xmibuflen)) != 0) {
297 goto cleanup;
298 }
299
300 /* decompress it! */
301 t1 = clock();
302 for (i=0; i<times; i++) {
303 try {
304 xmill->Decompress(xmibuf,
305 blocksize > 0 ? min(blocksize, xmibuflen) : xmibuflen,
306 &xmlbuf2, &xmlbuflen2,
307 &bytesread);
308 } catch (XMillException *e) {
309 stat = e->code;
310 errstr = e->GetErrorMsg();
311 delete e;
312 goto cleanup;
313 }
314 /* check that input==output */
315 stat = checkintegrity(xmlbuf, xmlbuflen, xmlbuf2, xmlbuflen2);
316 }
317
318 t2 = clock() - t1;
319 if (stats >= TEST_STATS_TIMING
320 || (stat != 0 && stats >= TEST_STATS_ERR && !mustfail)) {
321 printf("Done uncompressing %s %ld times.\n", xmifile, times);
322 }
323 if (stat < 0) {
324 stat = 0;
325 }
326
327 if (stats >= TEST_STATS_TIMING && !mustfail) {
328 /* print stats */
329 printf ("xml: %ld Bytes, xmi: %ld Bytes\n", xmlbuflen, xmibuflen);
330 /* print timings */
331 printf ("total clocks: %ld\naverage throughput: %lf KiB XML/sec, %lf KiB XMI/sec\n",
332 t2,
333 (double)xmlbuflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t2),
334 (double)xmibuflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t2));
335 }
336
337 cleanup:
338 /* free some data */
339 tryfree (xmlbuf);
340 tryfree (xmibuf);
341 tryfree (xmlbuf2);
342
343 return stat;
344 }
345
346 /* compress XML file 'filename' 'times' times, using type 'lossy' */
runcompdecomp(char * filename,int targetsize)347 int testsettings::runcompdecomp(char *filename, int targetsize)
348 {
349 int i = 0, numexprs = 0;
350 char *buffer = NULL;
351 int buflen = 0;
352 int stat = 0, thestat = 0;
353 char **pathexprs = NULL;
354 bool exprsnow = exprs;
355 clock_t t2 = 0, t3 = 0;
356 int xmibuflen;
357
358 /* read the file to memory */
359 if ((stat = readfile(filename, &buffer, &buflen)) != 0) {
360 goto cleanup;
361 }
362
363 if (exprsnow) {
364 exprsnow = false;
365 pathexprs = (char**)malloc(MAXEXPRS*sizeof(char*));
366 /* read .xmill file to memory */
367 if ((stat = XMill::readExprsFromFile(filename, pathexprs, MAXEXPRS, &numexprs)) == 0) {
368 /* set these path exprs */
369 try {
370 xmill->Init (XMILL_OUT_STRING_OR_FILE, XMILL_INIT_USERINIT, lossy, xmill->GetCompressionMode(), pathexprs,
371 false, 'n', true, -1, 1, gpcidx);
372 } catch (XMillException *e) {
373 stat = e->code;
374 errstr = e->GetErrorMsg();
375 delete e;
376 goto cleanup;
377 }
378 exprsnow = true;
379 }
380 stat = 0;
381 }
382
383 for (i=0; i<times; i++) {
384 if (stats >= TEST_STATS_ALL) {
385 printf("(de)compressing %s run %ld/%ld\n", filename, i+1, times);
386 }
387 /* compress and decompress the file, then check consistency */
388 if ((stat = compdecomp(buffer, buflen, filename, targetsize, &t2, &t3, &xmibuflen, i==0)) != 0) {
389 goto prematureexit;
390 }
391 }
392
393 prematureexit:
394 /* cleanup pathexprs */
395 if (exprsnow) {
396 try {
397 xmill->Init (XMILL_OUT_STRING_OR_FILE, XMILL_INIT_USERINIT, lossy, xmill->GetCompressionMode(), NULL,
398 false, 'n', true, -1, 1, gpcidx);
399 } catch (XMillException *e) {
400 stat = e->code;
401 errstr = e->GetErrorMsg();
402 delete e;
403 goto cleanup;
404 }
405 }
406
407 if (stat != 0) {
408 if (stats >= TEST_STATS_ERR && !mustfail) {
409 printf("Error while compressing & decompressing %s in run %ld/%ld.\n",
410 filename, i+1, times);
411 if (times > i+1) {
412 printf("Skipped next %ld run(s).\n", times-i-1);
413 }
414 printf("\n");
415 }
416 } else if (stats >= TEST_STATS_TIMING && !mustfail) {
417 /* print timings */
418 printf ("timing for %s:\n"
419 "\ttotal compress clocks: %ld\n\taverage throughput: %6.1lf KiB XML/s, %6.1lf KiB XMI/s\n"
420 "\ttotal decompress clocks: %ld\n\taverage throughput: %6.1lf KiB XML/s, %6.1lf KiB XMI/s\n",
421 filename,
422 t2, (double)buflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t2),
423 (double)xmibuflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t2),
424 t3, (double)buflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t3),
425 (double)xmibuflen * (double)CLOCKS_PER_SEC * (double)times / (1024.0 * (double)t3));
426 if (stats >= TEST_STATS_ALL) {
427 printf("Done compressing & decompressing %s %ld times.\n",
428 filename, times);
429 }
430 }
431
432 cleanup:
433 /* free XML data */
434 tryfree(buffer);
435 if (exprsnow) {
436 i = 0;
437 while (pathexprs && pathexprs[i]) {
438 tryfree(pathexprs[i]);
439 i++;
440 }
441 }
442 tryfree(pathexprs);
443
444 return stat;
445 }
446
testsettings()447 testsettings::testsettings()
448 {
449 xmill = new XMill();
450 times = 1;
451 lossy = true;
452 bzip = XMILL_GPC_BZIP;
453 gpcidx = XMILL_GZIP_IDX;
454 mode = TEST_COMPDECOMP;
455 exprs = false;
456 stats = TEST_STATS_WARN;
457 ignorewhite = false;
458 blocksize = 0;
459 mustfail = false;
460 }
461
~testsettings()462 testsettings::~testsettings()
463 {
464 delete xmill;
465 }
466
setstats(char s)467 void testsettings::setstats(char s)
468 {
469 stats = s;
470 }
471
parsesetting(char * s,char * s1,bool * usedboth)472 int testsettings::parsesetting(char *s, char *s1, bool *usedboth)
473 {
474 if (usedboth) {
475 *usedboth = false;
476 }
477
478 if (!stricmp(s, "gzip")) {
479 bzip = XMILL_GPC_GZIP;
480 gpcidx = XMILL_GZIP_IDX;
481 } else if (!stricmp(s, "nozip")) {
482 bzip = XMILL_GPC_NONE;
483 gpcidx = -1;
484 } else if (!stricmp(s, "bzip2")) {
485 bzip = XMILL_GPC_BZIP;
486 gpcidx = -1;
487 } else if (!stricmp(s, "ppmdi")) {
488 bzip = XMILL_GPC_PPMDI;
489 gpcidx = XMILL_PPMDI_IDX;
490 } else if (!stricmp(s, "lossless")) {
491 lossy = false;
492 } else if (!stricmp(s, "lossy")) {
493 lossy = true;
494 } else if (!stricmp(s, "compdecomp")) {
495 mode = TEST_COMPDECOMP;
496 } else if (!stricmp(s, "decomp")) {
497 mode = TEST_DECOMP;
498 } else if (!stricmp(s, "targetsize")) {
499 mode = TEST_TARGETSIZE;
500 } else if (!stricmp(s, "exprs")) {
501 exprs = true;
502 } else if (!stricmp(s, "plain")) {
503 exprs = false;
504 } else if (!stricmp(s, "gpcidx") && s1 && usedboth) {
505 gpcidx = atoi(s1);
506 *usedboth = true;
507 } else if (!stricmp(s, "verbose") && s1 && usedboth) {
508 xmill->SetVerbose(atoi(s1));
509 *usedboth = true;
510 } else if (!stricmp(s, "stats") && s1 && usedboth) {
511 setstats(atoi(s1));
512 *usedboth = true;
513 } else if (!stricmp(s, "silent")) {
514 xmill->SetVerbose(XMILL_VERBOSE_SILENT);
515 } else if (!stricmp(s, "noinc")) {
516 xmill->SetNoIncrease();
517 } else if (!stricmp(s, "allowinc")) {
518 xmill->SetNoIncrease(false);
519 } else if (!stricmp(s, "blocks") && s1 && usedboth) {
520 blocksize = atoi(s1);
521 *usedboth = true;
522 } else if (!stricmp(s, "ignorewhite")) {
523 ignorewhite = true;
524 } else if (!stricmp(s, "exact")) {
525 ignorewhite = false;
526 } else if (!stricmp(s, "mustfail")) {
527 mustfail = true;
528 } else if (!stricmp(s, "mustnotfail")) {
529 mustfail = false;
530 } else if (!stricmp(s, "quit")) {
531 return 1;
532 }
533 return 0;
534 }
535
run(char ** files,int numfiles)536 int testsettings::run(char **files, int numfiles)
537 {
538 int i = 0, stat = 0;
539 bool mustreinit = true;
540 int lasterrstat = 0;
541
542 switch (mode) {
543 case TEST_COMPDECOMP:
544 for (i=0; i<numfiles; i++) {
545 if (mustreinit) {
546 try {
547 xmill->Init (XMILL_OUT_STRING_OR_FILE, XMILL_INIT_USERINIT, lossy, bzip, NULL, false,
548 'n', true, -1, 1, gpcidx);
549 } catch (XMillException *e) {
550 stat = e->code;
551 errstr = e->GetErrorMsg();
552 delete e;
553 if (stats >= TEST_STATS_ERR && !mustfail) {
554 printf("error initializing: code %ld, text '%s'\n\n",
555 stat, errstr ? errstr : "");
556 }
557 goto cleanup;
558 }
559 mustreinit = false;
560 }
561 /* compress and decompress all files a few times */
562 if ((stat = runcompdecomp(files[i])) != 0) {
563 if (stats >= TEST_STATS_ERR && !mustfail) {
564 printf("error (de)compressing %s: code %ld, text '%s'\n\n",
565 files[i], stat, stat > 0 && errstr ? errstr : "");
566 }
567 /* we *must* reinitialize after a failure */
568 mustreinit = true;
569 lasterrstat = stat;
570 } else if (stats >= TEST_STATS_TIMING) {
571 printf("\n");
572 }
573 }
574 break;
575
576 case TEST_DECOMP:
577 for (i=0; i<numfiles-1; i+=2) {
578 if (mustreinit) {
579 try {
580 xmill->Init (XMILL_OUT_STRING_OR_FILE, XMILL_INIT_USERINIT, lossy, bzip, NULL, false
581 , 'n', true, -1, 1, gpcidx);
582 } catch (XMillException *e) {
583 stat = e->code;
584 errstr = e->GetErrorMsg();
585 delete e;
586 if (stats >= TEST_STATS_ERR && !mustfail) {
587 printf("error initializing: code %ld, text '%s'\n\n",
588 stat, errstr ? errstr : "");
589 }
590 goto cleanup;
591 }
592 mustreinit = false;
593 }
594 /* decompress all files a few times and check consistency */
595 if ((stat = rundecomp(files[i], files[i+1], times)) != 0) {
596 if (stats >= TEST_STATS_ERR && !mustfail) {
597 printf("error in %s / %s: code %ld, text '%s'\n\n",
598 files[i], files[i+1], stat, stat > 0 && errstr ? errstr : "");
599 }
600 /* we *must* reinitialize after a failure */
601 mustreinit = true;
602 lasterrstat = stat;
603 } else if (stats >= TEST_STATS_TIMING) {
604 printf("\n");
605 }
606 }
607 break;
608
609 case TEST_TARGETSIZE:
610 for (i=1; i<numfiles; i++) {
611 if (mustreinit) {
612 try {
613 xmill->Init (XMILL_OUT_STRING_OR_FILE, XMILL_INIT_USERINIT, lossy, bzip, NULL, false
614 , 'n', true, -1, 1, gpcidx);
615 } catch (XMillException *e) {
616 stat = e->code;
617 errstr = e->GetErrorMsg();
618 delete e;
619 if (stats >= TEST_STATS_ERR && !mustfail) {
620 printf("error initializing: code %ld, text '%s'\n\n",
621 stat, errstr ? errstr : "");
622 }
623 goto cleanup;
624 }
625 mustreinit = false;
626 }
627 /* compress and decompress all files a few times */
628 if ((stat = runcompdecomp(files[i], atoi(files[0]))) != 0) {
629 if (stats >= TEST_STATS_ERR && !mustfail) {
630 printf("error (de)compressing %s: code %ld, text '%s'\n\n",
631 files[i], stat, stat > 0 && errstr ? errstr : "");
632 }
633 /* we *must* reinitialize after a failure */
634 mustreinit = true;
635 lasterrstat = stat;
636 } else if (stats >= TEST_STATS_TIMING) {
637 printf("\n");
638 }
639 }
640 break;
641
642 default:
643 stat = TEST_ERROR_MODE;
644 break;
645 }
646
647 cleanup:
648 if (stat == 0 && lasterrstat != 0) {
649 stat = lasterrstat;
650 }
651
652 return stat;
653 }
654
trim(char * s)655 static char *trim(char *s)
656 {
657 int i=0, j=strlen(s)-1, k=0;
658 while(s[i] && isspace(s[i])) i++;
659 while(j>=i && isspace(s[j])) j--;
660 while (i<=j) {
661 s[k++] = s[i++];
662 }
663 s[k] = '\0';
664 return s;
665 }
666
run(FILE * script)667 int testsettings::run(FILE *script)
668 {
669 char line[STRLEN+1], *str = NULL, *str1 = NULL;
670 int numfiles = 0, stat = 0;
671 char *files[MAXFILES];
672 bool usedboth;
673 bool founderrors = false;
674
675 while (!feof(script)) {
676 /* get a line from the script & trim whitespaces */
677 fgets(line, STRLEN, script);
678 trim(line);
679 if (strlen(line) > 0) {
680 /* take an action based on the first character */
681 switch (line[0]) {
682 case '*':
683 /* setting */
684 str = strtok(&line[1], " ");
685 do {
686 /* parse all settings */
687 str1 = strtok(NULL, " ");
688 if (parsesetting(str, str1, &usedboth) == 1) {
689 /* 'quit' setting */
690 goto cleanup;
691 }
692 if (usedboth) {
693 /* skip setting argument */
694 str = strtok(NULL, " ");
695 } else {
696 str = str1;
697 }
698 } while (str);
699 break;
700
701 case '#':
702 /* comment */
703 break;
704
705 default:
706 /* command */
707 str = strtok(line, " ");
708 times = atoi(str);
709 numfiles = -1;
710 while (files[++numfiles] = strtok(NULL, " "));
711 if ((stat = run(files, numfiles)) != 0) {
712 /* ignore error, continue */
713 if (!mustfail) {
714 founderrors = true;
715 }
716 stat = 0;
717 } else if (mustfail) {
718 printf("Previous test should fail but succeeded!\n");
719 founderrors = true;
720 }
721 }
722 }
723 }
724
725 cleanup:
726 if (stat == 0 && founderrors) {
727 stat = TEST_ERROR_FOUND;
728 }
729
730 return stat;
731 }
732