|
|
1.1 root 1: /* Suite++: The Plum Hall Validation Suite for C++
2: * VERSION: 1
3: * AND The Plum Hall Validation Suite for C
4: * VERSION: 4
5: * Unpublished copyright (c) 1991, Plum Hall Inc (Editor)
6: * DATE: 1993-01-01
7: * As per your license agreement, your distribution is not to be moved or copied outside the Designated Site
8: * without specific permission from Plum Hall Inc.
9: */
10:
11: /*
12: * UTIL - various utility routines
13: */
14: #include "defs.h"
15: #ifndef FREESTANDING
16: #include <stdio.h>
17: #endif
18:
19: #define BUFSIZE 256
20:
21: void setzero();
22: void setremark();
23: void trace PARMS((const char *msg, int line));
24:
25: long Nerrs = 0;
26: long Nskips = 0;
27: long Nremarks = 0;
28: long Nsuccess = 0;
29: int Debug = FALSE;
30: char *Filename = 0;
31: char last_char_printed = 0;
32: static char details[BUFSIZE] = {0};
33: static int trace_msg_len = 0;
34: static char trace_routine[20] = "";
35: static char trace_filename[BUFSIZE] = "";
36: static int remarks = FALSE;
37: static int first = 1;
38:
39: #include "clib.h"
40:
41: /*
42: * STR_REV - reverse a string
43: */
44: char *str_rev FN_DEF1(s,
45: char *s)
46: {
47: char c;
48: char *p, *q;
49:
50: for (p = s, q = s + str_len(s) - 1; p < q; ++p, --q)
51: {
52: c = *p;
53: *p = *q;
54: *q = c;
55: }
56: return s;
57: }
58:
59: /*
60: * IABS - absolute value of an integer
61: */
62: int iabs FN_DEF1(i,
63: int i)
64: {
65: return (i >= 0) ? i : -i;
66: }
67:
68: /*
69: * DABS - absolute value of a double
70: */
71: double dabs FN_DEF1(d,
72: double d)
73: {
74: return (d >= 0.0) ? d : -d;
75: }
76:
77: /*
78: * DPOWU - returns a double d raised to the power of unsigned u
79: */
80: double dpowu FN_DEF2(d, u,
81: double d,
82: unsigned u)
83: {
84: double p = 1.0;
85:
86: while (u-- > 0)
87: p *= d;
88: return p;
89: }
90:
91: /*
92: * ULTOSTR - convert unsigned long u to a string in base b, return the
93: * address of the null terminator
94: */
95: char *ultostr FN_DEF3(s, u, b,
96: char *s,
97: ULONG u,
98: unsigned b)
99: {
100: char *p = s;
101:
102: do
103: {
104: if ((*p = u % b) < 10)
105: *p += '0';
106: else
107: *p += 'A' - 10;
108: ++p;
109: }
110: while ((u /= b) != 0);
111: *p = '\0';
112: str_rev(s);
113: return p;
114: }
115:
116: /*
117: * LTOSTR - convert long i to a string in base b
118: */
119: char *ltostr FN_DEF3(s, i, b,
120: char *s,
121: long i,
122: unsigned b)
123: {
124: if (i < 0)
125: {
126: *s++ = '-';
127: i = -i;
128: }
129: return ultostr(s, i, b);
130: }
131:
132: #define utostr(s, u, b) ultostr((s), (ULONG)(u), (b))
133:
134: #define itostr(s, i, b) ltostr((s), (long)(i), (b))
135:
136: #define ULONG_DIG 64
137:
138: /*
139: * PR_UL - print unsigned long u as a string in base b
140: */
141: void pr_ul FN_DEF2(lu, b,
142: ULONG lu,
143: unsigned b)
144: {
145: char buf[ULONG_DIG + 1];
146:
147: ultostr(buf, lu, b);
148: pr_ok(buf);
149: }
150:
151: /*
152: * PR_L - print long li as a string in base b
153: */
154: void pr_l FN_DEF2(li, b,
155: long li,
156: unsigned b)
157: {
158: char buf[ULONG_DIG + 2];
159:
160: ltostr(buf, li, b);
161: pr_ok(buf);
162: }
163:
164: #define pr_i(i, b) pr_l((long)(i), (b))
165:
166: /*
167: * ENTRY_FN - in Debug mode, record entry to a function
168: */
169: void entry_fn FN_DEF1(s,
170: const char *s)
171: {
172: if (Debug)
173: {
174: if (last_char_printed != '\n')
175: pr_ok("\n");
176: pr_ok("ENTERING: ");
177: pr_ok(s);
178: pr_ok("\n");
179: }
180: }
181:
182: /*
183: * ERRMSG - print and tabulate each message
184: */
185: static void errmsg FN_DEF2(msg, line,
186: char *msg,
187: int line)
188: {
189: if (first)
190: {
191: setzero();
192: setremark();
193: first = 0;
194: }
195: if (trace_msg_len != 0 )
196: {
197: if (last_char_printed != '\n')
198: pr_ok("\n");
199: trace_msg_len = 0;
200: str_cpye(trace_routine, "");
201: }
202: if (line > 0 || remarks)
203: {
204: pr_ok(line > 0 ? "ERROR" : "REMARK");
205: pr_ok(" in ");
206: pr_ok(Filename);
207: pr_ok(" at line ");
208: pr_i(iabs(line), 10);
209: pr_ok(msg);
210: pr_ok("\n");
211: }
212: if (line > 0)
213: ++Nerrs;
214: else
215: ++Nremarks;
216: }
217:
218: /*
219: * IEQUALS - 'int' equality check. If val1 != val2, then report an error.
220: */
221: int iequals FN_DEF3(line, val1, val2,
222: int line,
223: int val1,
224: int val2)
225: {
226: char *p;
227:
228: if (val1 != val2)
229: {
230: p = str_cpye(details, ": (");
231: p = itostr(p, val1, 10);
232: p = str_cpye(p, ") != (");
233: p = itostr(p, val2, 10);
234: p = str_cpye(p, ")");
235: errmsg(details, line);
236: return 0;
237: }
238: else
239: trace("iequals", line);
240: return 1;
241: }
242:
243: /*
244: * INOTEQUALS - 'int' non-equality check. If val1 == val2, then
245: * report an error.
246: */
247: int inotequals FN_DEF3(line, val1, val2,
248: int line,
249: int val1,
250: int val2)
251: {
252: char *p;
253:
254: if (val1 == val2)
255: {
256: p = str_cpye(details, ": (");
257: p = itostr(p, val1, 10);
258: p = str_cpye(p, ") == (");
259: p = itostr(p, val2, 10);
260: p = str_cpye(p, ")");
261: errmsg(details, line);
262: return 0;
263: }
264: else
265: trace("inotequals", line);
266: return 1;
267: }
268:
269: /*
270: * LEQUALS - 'long' equality check. If val1 != val2, then
271: * report an error.
272: */
273: int lequals FN_DEF3(line, val1, val2,
274: int line,
275: long val1,
276: long val2)
277: {
278: char *p;
279:
280: if (val1 != val2)
281: {
282: p = str_cpye(details, ": (");
283: p = ltostr(p, val1, 10);
284: p = str_cpye(p, ") != (");
285: p = ltostr(p, val2, 10);
286: p = str_cpye(p, ")");
287: errmsg(details, line);
288: return 0;
289: }
290: else
291: trace("lequals", line);
292: return 1;
293: }
294:
295: /*
296: * ULEQUALS - 'unsigned long' equality check. If val1 != val2, then
297: * report an error.
298: */
299: int ulequals FN_DEF3(line, val1, val2,
300: int line,
301: ULONG val1,
302: ULONG val2)
303: {
304: char *p;
305:
306: if (val1 != val2)
307: {
308: p = str_cpye(details, ": (");
309: p = ultostr(p, val1, 10);
310: p = str_cpye(p, ") != (");
311: p = ultostr(p, val2, 10);
312: p = str_cpye(p, ")");
313: errmsg(details, line);
314: return 0;
315: }
316: else
317: trace("ulequals", line);
318: return 1;
319: }
320:
321: /*
322: * STEQUALS - string equality.
323: */
324: int stequals FN_DEF3(line, val1, val2,
325: int line,
326: const char *val1,
327: const char *val2)
328: {
329: char *p;
330:
331: if (str_cmp(val1, val2))
332: {
333: p = str_cpye(details, ": \"");
334: p = str_cpye(p, val1);
335: p = str_cpye(p, "\" != \"");
336: p = str_cpye(p, val2);
337: p = str_cpye(p, "\"");
338: errmsg(details, line);
339: return 0;
340: }
341: else
342: trace("stequals", line);
343: return 1;
344: }
345:
346: /*
347: * COMPLAIN - unconditional failure.
348: */
349: int complain FN_DEF1(line,
350: int line)
351: {
352: errmsg("", line);
353: return 0;
354: }
355:
356: /*
357: * ARBHEX - convert an arbitrary byte-sequence into hex codes
358: */
359: #ifndef CHAR_BIT
360: #define CHAR_BIT 8
361: #endif
362: #define NIBBLES_PER_BYTE ((CHAR_BIT + 3) / 4)
363:
364: char *arbhex FN_DEF3(str, p, n,
365: char *str,
366: const char *p,
367: int n)
368: {
369: int i, nib, hex_dig;
370: static char codes[] = "0123456789ABCDEF";
371:
372: for (i = 0; i < n; ++i, ++p)
373: for (nib = NIBBLES_PER_BYTE - 1; nib >= 0; --nib)
374: {
375: hex_dig = (*p & (unsigned)(0xF << (nib * 4))) >> (nib * 4);
376: *str++ = codes[hex_dig];
377: }
378: *str = '\0';
379: return str;
380: }
381:
382: /*
383: * AEQUALS - 'address' equality check. If val1 != val2, then
384: * report an error.
385: */
386: int aequals FN_DEF3(line, val1, val2,
387: int line,
388: const void *val1,
389: const void *val2)
390: {
391: #ifdef FREESTANDING
392: char *p;
393: #endif
394:
395: if (val1 != val2)
396: {
397: #ifdef FREESTANDING
398: p = str_cpye(details, ": (");
399: p = arbhex(p, (const char *)&val1, (int)sizeof(val1));
400: p = str_cpye(p, ") != (");
401: p = arbhex(p, (const char *)&val2, (int)sizeof(val2));
402: p = str_cpye(p, ")");
403: #else
404: sprintf(details, ": (%p) != (%p)", val1, val2);
405: #endif
406: errmsg(details, line);
407: return 0;
408: }
409: else
410: trace("aequals", line);
411: return 1;
412: }
413:
414: /*
415: * FAEQUALS - function address equality check. If val1 != val2, then
416: * report an error. The address of a function is not necessarily the same
417: * size/type as the address of data.
418: */
419: int faequals FN_DEF3(line, val1, val2,
420: int line,
421: int (*val1)(),
422: int (*val2)())
423: {
424: char *p;
425:
426: if (val1 != val2)
427: {
428: p = str_cpye(details, ": (");
429: p = arbhex(p, (char *)&val1, (int)sizeof(val1));
430: p = str_cpye(p, ") != (");
431: p = arbhex(p, (char *)&val2, (int)sizeof(val2));
432: p = str_cpye(p, ")");
433: errmsg(details, line);
434: return 0;
435: }
436: else
437: trace("faequals", line);
438: return 1;
439: }
440:
441: /*
442: * DEQUALS - 'double' equality check. If val1 != val2, then
443: * report an error. This is computed using an equality approximation
444: * that verifies that the two numbers are equal to R digits whenever
445: *
446: * |x - y| 1 1-R
447: * ------- <= - 10
448: * |x| 2
449: *
450: * DIGITS_MAX is defined in defs.h
451: */
452: double Delta = 0.0;
453:
454: int dequals FN_DEF3(line, val1, val2,
455: int line,
456: double val1,
457: double val2)
458: {
459: #ifdef FREESTANDING
460: char *p;
461: #endif
462: double *pd;
463:
464: if (line < 0) /* no "remarks" for floating point */
465: return 0;
466: if (Delta == 0.0)
467: Delta = 0.5 / dpowu(10.0, DIGITS_MAX - 1);
468: if (val1 == val2)
469: {
470: trace("dequals", line);
471: return 1;
472: }
473: pd = &val1;
474: if (val1 == 0.0)
475: pd = &val2;
476:
477: /* special cases to handle zero against very small numbers */
478: if (dabs(val1) == 0.0 && dabs(val2) < Delta)
479: ;
480: else if (dabs(val2) == 0.0 && dabs(val1) < Delta)
481: ;
482: else if ((dabs(val1 - val2) / dabs(*pd)) > Delta)
483: {
484: #ifdef FREESTANDING
485: p = str_cpye(details, ": (");
486: p = arbhex(p, (const char *)&val1, (int)sizeof(val1));
487: p = str_cpye(p, ") != (");
488: p = arbhex(p, (const char *)&val2, (int)sizeof(val2));
489: p = str_cpye(p, ")");
490: #else
491: sprintf(details, ": (%.*G) != (%.*G)",
492: DIGITS_MAX + 2, val1, DIGITS_MAX + 2, val2);
493: #endif
494: errmsg(details, line);
495: return 0;
496: }
497: trace("dequals", line);
498: return 1;
499: }
500:
501: #if ANSI
502: /*
503: * LDEQUALS - Long double equality ... more of the same.
504: */
505: #define ldabs(ld) ((ld) < 0.0 ? -(ld) : (ld))
506:
507: long double LDelta = 0.0;
508:
509: int ldequals FN_DEF3(line, val1, val2,
510: int line,
511: long double val1,
512: long double val2)
513: {
514: #ifdef FREESTANDING
515: char *p;
516: #endif
517: long double *pd;
518:
519: if (line < 0) /* no "remarks" for floating point */
520: return 0;
521: if (LDelta == 0.0)
522: {
523: LDelta = 0.5L / dpowu(10.0, LDIGITS_MAX - 1);
524: }
525: if (val1 == val2)
526: {
527: trace("ldequals", line);
528: return 1;
529: }
530: pd = &val1;
531: if (val1 == 0.0)
532: pd = &val2;
533:
534: /* special cases to handle zero against very small numbers */
535: if (ldabs(val1) == 0.0 && ldabs(val2) < LDelta)
536: ;
537: else if (ldabs(val2) == 0.0 && ldabs(val1) < LDelta)
538: ;
539: else if ((ldabs(val1 - val2) / ldabs(*pd)) > LDelta)
540: {
541: #ifdef FREESTANDING
542: p = str_cpye(details, ": (");
543: p = arbhex(p, (char *)&val1, (int)sizeof(val1));
544: p = str_cpye(p, ") != (");
545: p = arbhex(p, (char *)&val2, (int)sizeof(val2));
546: p = str_cpye(p, ")");
547: #else
548: sprintf(details, ": (%.*LE) != (%.*LE)",
549: LDIGITS_MAX + 2, val1, LDIGITS_MAX + 2, val2);
550: #endif
551: errmsg(details, line);
552: return 0;
553: }
554: trace("ldequals", line);
555: return 1;
556: }
557: #endif
558:
559: /*
560: * FEQUALS - same as DEQUALS, but to FDIGITS_MAX instead of DIGITS_MAX.
561: */
562: double FDelta = 0.0;
563:
564: int fequals FN_DEF3(line, in1, in2,
565: int line,
566: double in1,
567: double in2)
568: {
569: #ifdef FREESTANDING
570: char *p;
571: #endif
572: float *pf;
573: float val1 = in1;
574: float val2 = in2;
575:
576: if (line < 0) /* no "remarks" for floating point */
577: return 0;
578: if (FDelta == 0.0)
579: FDelta = 0.5 / dpowu(10.0, FDIGITS_MAX - 1);
580: if (val1 == val2)
581: {
582: trace("fequals", line);
583: return 1;
584: }
585: pf = &val1;
586: if (val1 == 0.0)
587: pf = &val2;
588:
589: /* special cases to handle zero against very small numbers */
590: if (dabs(val1) == 0.0 && dabs(val2) < FDelta)
591: ;
592: else if (dabs(val2) == 0.0 && dabs(val1) < FDelta)
593: ;
594: else if ((dabs(val1 - val2) / dabs(*pf)) > FDelta)
595: {
596: #ifdef FREESTANDING
597: p = str_cpye(details, ": (");
598: p = arbhex(p, (char *)&val1, (int)sizeof(val1));
599: p = str_cpye(p, ") != (");
600: p = arbhex(p, (char *)&val2, (int)sizeof(val2));
601: p = str_cpye(p, ")");
602: #else
603: sprintf(details, ": (%.*G) != (%.*G)",
604: FDIGITS_MAX+2, val1, FDIGITS_MAX+2, val2);
605: #endif
606: errmsg(details, line);
607: return 0;
608: }
609: trace("fequals", line);
610: return 1;
611: }
612:
613: /*
614: * CHECKTHAT - simple condition check. If val1 == 0, then
615: * report an error.
616: */
617: int checkthat FN_DEF2(line, cond,
618: int line,
619: int cond)
620: {
621: if (!cond)
622: {
623: errmsg("", line);
624: return 0;
625: }
626: else
627: trace("checkthat", line);
628: return 1;
629: }
630:
631: /*
632: * VALUE - the value routines are used to defeat value propagation in
633: * optimizing compilers. We want to make sure that we are testing what we
634: * think we are testing, not what the compiler transformed it to.
635: * 1988: Some compilers "open-code" all small functions. Now we have to hide
636: * the constants still further.
637: */
638: static int Zero = 0; /* See setzero() below */
639:
640: int ivalue FN_DEF1(i,
641: int i)
642: {
643: return i + Zero;
644: }
645:
646: long lvalue FN_DEF1(i,
647: long i)
648: {
649: return i + Zero;
650: }
651:
652: double dvalue FN_DEF1(i,
653: double i)
654: {
655: return i + Zero;
656: }
657:
658: float fvalue FN_DEF1(i,
659: double i)
660: {
661: return (float)i + Zero;
662: }
663:
664: generic_ptr avalue FN_DEF1(i,
665: generic_ptr i)
666: {
667: if (i == 0)
668: return 0;
669: else
670: return (char *)i + Zero;
671: }
672:
673: /*
674: * SCHECK - check both values and side effects.
675: */
676: int Side = 0;
677:
678: int scheck FN_DEF4(line, val1, se, val2,
679: int line,
680: int val1,
681: int se,
682: int val2)
683: {
684: int status = 1;
685:
686: if (Side != se)
687: {
688: errmsg(": incorrect side effect", line);
689: status = 0;
690: }
691: else
692: trace("scheck", line);
693: Side = 0;
694: return status == 1 && iequals(line, val1, val2);
695: }
696:
697: /*
698: * DO_NOTHING - this is also intended to defeat optimizers by passing
699: * the addresses of variables for which we want to stop any value propagation.
700: */
701: int do_nothing FN_DEF1V(p,
702: void *p)
703: {
704: *(char *)p = *((char *)p + Zero);
705: return 0;
706: }
707:
708: /*
709: * REPORT - summary report at end of testing.
710: */
711: int report FN_DEF1(program,
712: const char *program)
713: {
714: Nerrs += Nskips;
715: return Nerrs > MAX_INT ? MAX_INT : (int)Nerrs;
716: }
717:
718: /*
719: * DBPRINT - print the message if the Debug flag is on.
720: */
721: void dbprint FN_DEF1(s,
722: const char *s)
723: {
724: if (Debug)
725: {
726: pr_ok("***DEBUG***");
727: pr_ok(s);
728: }
729: }
730:
731: /*
732: * TRACE - print a line-number trace for debugging
733: * Also count successful tests.
734: */
735: void trace FN_DEF2(routine, line,
736: const char *routine,
737: int line)
738: {
739: char buf[10];
740:
741: if (first)
742: {
743: setzero();
744: setremark();
745: first = 0;
746: }
747: if (Debug && line > 0)
748: {
749: if (str_cmp(trace_routine, routine) != 0 ||
750: str_cmp(trace_filename, Filename) != 0 ||
751: last_char_printed == '\n' ||
752: trace_msg_len > 60)
753: {
754: if (last_char_printed != '\n')
755: pr_ok("\n");
756: pr_ok("TRACE: ");
757: pr_ok(routine);
758: pr_ok(" at ");
759: pr_ok(Filename);
760: pr_ok(" ");
761: str_cpye(trace_routine, routine);
762: str_cpye(trace_filename, Filename);
763: trace_msg_len = 11 + str_len(routine) + str_len(Filename);
764: }
765: str_cpye(itostr(buf, iabs(line), 10), " ");
766: pr_ok(buf);
767: trace_msg_len += str_len(buf);
768: }
769: if (line > 0)
770: ++Nsuccess; /* don't count remarks in score */
771: }
772:
773: /*
774: * PR_SKIP - printf a text line in SKIP situation
775: */
776: void pr_skip FN_DEF1(s,
777: const char *s)
778: {
779: ++Nskips;
780: if (last_char_printed != '\n')
781: pr_ok("\n");
782: pr_ok("SKIPPED: ");
783: pr_ok(s);
784: pr_ok("\n");
785: }
786:
787: /*
788: * PR_ERR - printf a text line in error situation
789: */
790: void pr_err FN_DEF1(s,
791: const char *s)
792: {
793: ++Nerrs;
794: pr_ok(s);
795: }
796: /*
797: * SETREMARK - determine whether "remark" messages should be printed
798: */
799: void setremark()
800: {
801: #ifdef SUITE_REMARK
802: remarks = TRUE;
803: #else
804: remarks = FALSE;
805: #endif
806: }
807:
808: /*
809: * ignore - appear to use a value, but don't
810: * (Purpose: shut up noisy "value not used" messages)
811: */
812: void ignore FN_DEF1(addr,
813: const void *addr)
814: {
815: if (Zero)
816: pr_ok((char *)addr);
817: }
818:
819: #include "sdutil.h"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.