/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1995-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* fmtre(3) and fmtmatch(3) test harness
* see help() for details
*/
#include <ast.h>
#include <ctype.h>
#include <setjmp.h>
#include <sig.h>
typedef char* (*Call_f)(const char*);
static void
help(void)
{
H("NAME\n");
H(" testfmt - fmtre(3) and fmtmatch(3) test harness\n");
H("\n");
H("SYNOPSIS\n");
H(" testfmt [ options ] < testfmt.dat\n");
H("\n");
H("DESCRIPTION\n");
H(" testfmt reads test specifications, one per line, from the standard\n");
H(" input and writes one output line for each failed test. A summary\n");
H(" line is written after all tests are done.\n");
H("\n");
H("OPTIONS\n");
H(" -c catch signals and non-terminating calls\n");
H(" -h list help\n");
H(" -v list each test line\n");
H("\n");
H("INPUT FORMAT\n");
H(" Input lines may be blank, a comment beginning with #, or a test\n");
H(" specification. A specification is three fields separated by one\n");
H(" or more tabs. NULL denotes the empty string and NIL denotes the\n");
H(" 0 pointer.\n");
H("\n");
H(" Field 1: the pattern type:\n");
H("\n");
H(" E ERE (egrep)\n");
H(" K KRE (ksh glob)\n");
H(" i invert test the inverse call too\n");
H("\n");
H(" $ expand C \\c escapes in fields 2 and 3\n");
H(" : comment comment copied to output\n");
H("\n");
H(" Field 2: the regular expression pattern.\n");
H("\n");
H(" Field 3: the converted pattern to match.\n");
H("\n");
H(" Field 4: optional comment appended to the report.\n");
H("\n");
H("CONTRIBUTORS\n");
H(" Glenn Fowler <gsf@research.att.com>\n");
H(" David Korn <dgk@research.att.com>\n");
}
static struct
{
int errors;
int lineno;
int signals;
int warnings;
char* file;
} state;
static void
{
unsigned char* u = (unsigned char*)s;
int c;
if (!u)
else if (!*u)
else if (expand)
{
for (;;)
{
switch (c = *u++)
{
case 0:
break;;
case '\\':
continue;
case '"':
continue;
case '\a':
continue;
case '\b':
continue;
case '\f':
continue;
case '\n':
continue;
case '\r':
continue;
case '\t':
continue;
case '\v':
continue;
default:
else
continue;
}
break;
}
}
else
}
static void
{
if (fun)
if (re)
{
}
}
static void
{
exit(1);
}
static void
escape(char* s)
{
char* e;
char* t;
char* q;
int c;
for (t = s; *t = *s; s++, t++)
if (*s == '\\')
switch (*++s)
{
case '\\':
break;
case 'a':
*t = '\a';
break;
case 'b':
*t = '\b';
break;
case 'c':
if (*t = *++s)
*t &= 037;
else
s--;
break;
case 'e':
case 'E':
*t = 033;
break;
case 'f':
*t = '\f';
break;
case 'n':
*t = '\n';
break;
case 'r':
*t = '\r';
break;
case 's':
*t = ' ';
break;
case 't':
*t = '\t';
break;
case 'v':
*t = '\v';
break;
case 'u':
case 'x':
q = *s == 'u' ? (s + 4) : (char*)0;
c = 0;
e = s;
while (!e || !q || s < q)
{
switch (*s)
{
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
c = (c << 4) + *s++ - 'a' + 10;
continue;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
c = (c << 4) + *s++ - 'A' + 10;
continue;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = (c << 4) + *s++ - '0';
continue;
case '{':
case '[':
if (s != e)
break;
e = 0;
s++;
if (q && *s == 'U' && *(s + 1) == '+')
s += 2;
continue;
case '}':
case ']':
if (!e)
s++;
break;
default:
break;
}
break;
}
*t = c;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = *s - '0';
q = s + 2;
while (s < q)
switch (*++s)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = (c << 3) + *s - '0';
break;
default:
q = --s;
break;
}
*t = c;
break;
default:
}
}
static void
{
alarm(0);
}
int
{
int expand;
int type;
int invert;
int i;
int subunitlen;
int testno;
char* p;
char* spec;
char* re;
char* s;
char* ans;
char* msg;
char* fun;
char* subunit;
char* version;
int catch = 0;
int verbose = 0;
p = unit;
p++;
*p = 0;
while ((p = *++argv) && *p == '-')
for (;;)
{
switch (*++p)
{
case 0:
break;
case 'c':
catch = 1;
continue;
case 'h':
case '?':
case '-':
help();
return 2;
case 'v':
verbose = 1;
continue;
default:
return 1;
}
break;
}
if (catch)
{
}
if (!*argv)
{
{
}
{
return 2;
}
{
subunit = p = 0;
for (;;)
{
switch (*s++)
{
case 0:
break;
case '/':
subunit = s;
continue;
case '.':
p = s - 1;
continue;
default:
continue;
}
break;
}
if (!subunit)
if (p < subunit)
p = s - 1;
subunitlen = p - subunit;
subunit = 0;
else
}
else
subunit = 0;
if (catch)
if (verbose)
{
/* parse: */
if (*p == 0 || *p == '#')
continue;
if (*p == ':')
{
while (*++p == ' ');
continue;
}
i = 0;
field[i++] = p;
for (;;)
{
switch (*p++)
{
case 0:
p--;
goto checkfield;
case '\t':
*(p - 1) = 0;
s = field[i - 1];
if (streq(s, "NIL"))
field[i - 1] = 0;
else if (streq(s, "NULL"))
*s = 0;
while (*p == '\t')
p++;
if (!*p)
break;
if (i >= elementsof(field))
field[i++] = p;
/*FALLTHROUGH*/
default:
continue;
}
break;
}
/* interpret: */
for (p = spec; *p; p++)
{
switch (*p)
{
case 'E':
continue;
case 'K':
continue;
case 'i':
invert = 1;
continue;
case '$':
expand = 1;
continue;
default:
break;
}
break;
}
if (i < 3)
while (i < elementsof(field))
field[i++] = 0;
escape(s);
for (;;)
{
{
fun = "fmtmatch";
}
{
fun = "fmtre";
}
else
break;
testno++;
if (verbose)
if (!catch)
s = "SIGNAL";
else
{
alarm(0);
}
{
}
if (!invert)
break;
invert = 0;
s = ans;
re = s;
}
}
if (subunit)
}
return 0;
}