Initial revision
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10992 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
3e44f09d77
commit
5a41989248
242
src/regex/debug.c
Normal file
242
src/regex/debug.c
Normal file
@ -0,0 +1,242 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "regex2.h"
|
||||
#include "debug.ih"
|
||||
|
||||
/*
|
||||
- regprint - print a regexp for debugging
|
||||
== void regprint(regex_t *r, FILE *d);
|
||||
*/
|
||||
void
|
||||
regprint(r, d)
|
||||
regex_t *r;
|
||||
FILE *d;
|
||||
{
|
||||
register struct re_guts *g = r->re_g;
|
||||
register int i;
|
||||
register int c;
|
||||
register int last;
|
||||
int nincat[NC];
|
||||
|
||||
fprintf(d, "%ld states, %d categories", (long)g->nstates,
|
||||
g->ncategories);
|
||||
fprintf(d, ", first %ld last %ld", (long)g->firststate,
|
||||
(long)g->laststate);
|
||||
if (g->iflags&USEBOL)
|
||||
fprintf(d, ", USEBOL");
|
||||
if (g->iflags&USEEOL)
|
||||
fprintf(d, ", USEEOL");
|
||||
if (g->iflags&BAD)
|
||||
fprintf(d, ", BAD");
|
||||
if (g->nsub > 0)
|
||||
fprintf(d, ", nsub=%ld", (long)g->nsub);
|
||||
if (g->must != NULL)
|
||||
fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
|
||||
g->must);
|
||||
if (g->backrefs)
|
||||
fprintf(d, ", backrefs");
|
||||
if (g->nplus > 0)
|
||||
fprintf(d, ", nplus %ld", (long)g->nplus);
|
||||
fprintf(d, "\n");
|
||||
s_print(g, d);
|
||||
for (i = 0; i < g->ncategories; i++) {
|
||||
nincat[i] = 0;
|
||||
for (c = CHAR_MIN; c <= CHAR_MAX; c++)
|
||||
if (g->categories[c] == i)
|
||||
nincat[i]++;
|
||||
}
|
||||
fprintf(d, "cc0#%d", nincat[0]);
|
||||
for (i = 1; i < g->ncategories; i++)
|
||||
if (nincat[i] == 1) {
|
||||
for (c = CHAR_MIN; c <= CHAR_MAX; c++)
|
||||
if (g->categories[c] == i)
|
||||
break;
|
||||
fprintf(d, ", %d=%s", i, regchar(c));
|
||||
}
|
||||
fprintf(d, "\n");
|
||||
for (i = 1; i < g->ncategories; i++)
|
||||
if (nincat[i] != 1) {
|
||||
fprintf(d, "cc%d\t", i);
|
||||
last = -1;
|
||||
for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */
|
||||
if (c <= CHAR_MAX && g->categories[c] == i) {
|
||||
if (last < 0) {
|
||||
fprintf(d, "%s", regchar(c));
|
||||
last = c;
|
||||
}
|
||||
} else {
|
||||
if (last >= 0) {
|
||||
if (last != c-1)
|
||||
fprintf(d, "-%s",
|
||||
regchar(c-1));
|
||||
last = -1;
|
||||
}
|
||||
}
|
||||
fprintf(d, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- s_print - print the strip for debugging
|
||||
== static void s_print(register struct re_guts *g, FILE *d);
|
||||
*/
|
||||
static void
|
||||
s_print(g, d)
|
||||
register struct re_guts *g;
|
||||
FILE *d;
|
||||
{
|
||||
register sop *s;
|
||||
register cset *cs;
|
||||
register int i;
|
||||
register int done = 0;
|
||||
register sop opnd;
|
||||
register int col = 0;
|
||||
register int last;
|
||||
register sopno offset = 2;
|
||||
# define GAP() { if (offset % 5 == 0) { \
|
||||
if (col > 40) { \
|
||||
fprintf(d, "\n\t"); \
|
||||
col = 0; \
|
||||
} else { \
|
||||
fprintf(d, " "); \
|
||||
col++; \
|
||||
} \
|
||||
} else \
|
||||
col++; \
|
||||
offset++; \
|
||||
}
|
||||
|
||||
if (OP(g->strip[0]) != OEND)
|
||||
fprintf(d, "missing initial OEND!\n");
|
||||
for (s = &g->strip[1]; !done; s++) {
|
||||
opnd = OPND(*s);
|
||||
switch (OP(*s)) {
|
||||
case OEND:
|
||||
fprintf(d, "\n");
|
||||
done = 1;
|
||||
break;
|
||||
case OCHAR:
|
||||
if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
|
||||
fprintf(d, "\\%c", (char)opnd);
|
||||
else
|
||||
fprintf(d, "%s", regchar((char)opnd));
|
||||
break;
|
||||
case OBOL:
|
||||
fprintf(d, "^");
|
||||
break;
|
||||
case OEOL:
|
||||
fprintf(d, "$");
|
||||
break;
|
||||
case OBOW:
|
||||
fprintf(d, "\\{");
|
||||
break;
|
||||
case OEOW:
|
||||
fprintf(d, "\\}");
|
||||
break;
|
||||
case OANY:
|
||||
fprintf(d, ".");
|
||||
break;
|
||||
case OANYOF:
|
||||
fprintf(d, "[(%ld)", (long)opnd);
|
||||
cs = &g->sets[opnd];
|
||||
last = -1;
|
||||
for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */
|
||||
if (CHIN(cs, i) && i < g->csetsize) {
|
||||
if (last < 0) {
|
||||
fprintf(d, "%s", regchar(i));
|
||||
last = i;
|
||||
}
|
||||
} else {
|
||||
if (last >= 0) {
|
||||
if (last != i-1)
|
||||
fprintf(d, "-%s",
|
||||
regchar(i-1));
|
||||
last = -1;
|
||||
}
|
||||
}
|
||||
fprintf(d, "]");
|
||||
break;
|
||||
case OBACK_:
|
||||
fprintf(d, "(\\<%ld>", (long)opnd);
|
||||
break;
|
||||
case O_BACK:
|
||||
fprintf(d, "<%ld>\\)", (long)opnd);
|
||||
break;
|
||||
case OPLUS_:
|
||||
fprintf(d, "(+");
|
||||
if (OP(*(s+opnd)) != O_PLUS)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
break;
|
||||
case O_PLUS:
|
||||
if (OP(*(s-opnd)) != OPLUS_)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
fprintf(d, "+)");
|
||||
break;
|
||||
case OQUEST_:
|
||||
fprintf(d, "(?");
|
||||
if (OP(*(s+opnd)) != O_QUEST)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
break;
|
||||
case O_QUEST:
|
||||
if (OP(*(s-opnd)) != OQUEST_)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
fprintf(d, "?)");
|
||||
break;
|
||||
case OLPAREN:
|
||||
fprintf(d, "((<%ld>", (long)opnd);
|
||||
break;
|
||||
case ORPAREN:
|
||||
fprintf(d, "<%ld>))", (long)opnd);
|
||||
break;
|
||||
case OCH_:
|
||||
fprintf(d, "<");
|
||||
if (OP(*(s+opnd)) != OOR2)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
break;
|
||||
case OOR1:
|
||||
if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
fprintf(d, "|");
|
||||
break;
|
||||
case OOR2:
|
||||
fprintf(d, "|");
|
||||
if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
break;
|
||||
case O_CH:
|
||||
if (OP(*(s-opnd)) != OOR1)
|
||||
fprintf(d, "<%ld>", (long)opnd);
|
||||
fprintf(d, ">");
|
||||
break;
|
||||
default:
|
||||
fprintf(d, "!%d(%d)!", OP(*s), opnd);
|
||||
break;
|
||||
}
|
||||
if (!done)
|
||||
GAP();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- regchar - make a character printable
|
||||
== static char *regchar(int ch);
|
||||
*/
|
||||
static char * /* -> representation */
|
||||
regchar(ch)
|
||||
int ch;
|
||||
{
|
||||
static char buf[10];
|
||||
|
||||
if (isprint(ch) || ch == ' ')
|
||||
sprintf(buf, "%c", ch);
|
||||
else
|
||||
sprintf(buf, "\\%o", ch);
|
||||
return(buf);
|
||||
}
|
1019
src/regex/engine.c
Normal file
1019
src/regex/engine.c
Normal file
File diff suppressed because it is too large
Load Diff
510
src/regex/main.c
Normal file
510
src/regex/main.c
Normal file
@ -0,0 +1,510 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "main.ih"
|
||||
|
||||
char *progname;
|
||||
int debug = 0;
|
||||
int line = 0;
|
||||
int status = 0;
|
||||
|
||||
int copts = REG_EXTENDED;
|
||||
int eopts = 0;
|
||||
regoff_t startoff = 0;
|
||||
regoff_t endoff = 0;
|
||||
|
||||
|
||||
extern int split();
|
||||
extern void regprint();
|
||||
|
||||
/*
|
||||
- main - do the simple case, hand off to regress() for regression
|
||||
*/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
regex_t re;
|
||||
# define NS 10
|
||||
regmatch_t subs[NS];
|
||||
char erbuf[100];
|
||||
int err;
|
||||
size_t len;
|
||||
int c;
|
||||
int errflg = 0;
|
||||
register int i;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
while ((c = getopt(argc, argv, "c:e:S:E:x")) != EOF)
|
||||
switch (c) {
|
||||
case 'c': /* compile options */
|
||||
copts = options('c', optarg);
|
||||
break;
|
||||
case 'e': /* execute options */
|
||||
eopts = options('e', optarg);
|
||||
break;
|
||||
case 'S': /* start offset */
|
||||
startoff = (regoff_t)atoi(optarg);
|
||||
break;
|
||||
case 'E': /* end offset */
|
||||
endoff = (regoff_t)atoi(optarg);
|
||||
break;
|
||||
case 'x': /* Debugging. */
|
||||
debug++;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
errflg++;
|
||||
break;
|
||||
}
|
||||
if (errflg) {
|
||||
fprintf(stderr, "usage: %s ", progname);
|
||||
fprintf(stderr, "[-c copt][-C][-d] [re]\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
regress(stdin);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
err = regcomp(&re, argv[optind++], copts);
|
||||
if (err) {
|
||||
len = regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "error %s, %d/%d `%s'\n",
|
||||
eprint(err), len, sizeof(erbuf), erbuf);
|
||||
exit(status);
|
||||
}
|
||||
regprint(&re, stdout);
|
||||
|
||||
if (optind >= argc) {
|
||||
regfree(&re);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
if (eopts®_STARTEND) {
|
||||
subs[0].rm_so = startoff;
|
||||
subs[0].rm_eo = strlen(argv[optind]) - endoff;
|
||||
}
|
||||
err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
|
||||
if (err) {
|
||||
len = regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "error %s, %d/%d `%s'\n",
|
||||
eprint(err), len, sizeof(erbuf), erbuf);
|
||||
exit(status);
|
||||
}
|
||||
if (!(copts®_NOSUB)) {
|
||||
len = (int)(subs[0].rm_eo - subs[0].rm_so);
|
||||
if (subs[0].rm_so != -1) {
|
||||
if (len != 0)
|
||||
printf("match `%.*s'\n", len,
|
||||
argv[optind] + subs[0].rm_so);
|
||||
else
|
||||
printf("match `'@%.1s\n",
|
||||
argv[optind] + subs[0].rm_so);
|
||||
}
|
||||
for (i = 1; i < NS; i++)
|
||||
if (subs[i].rm_so != -1)
|
||||
printf("(%d) `%.*s'\n", i,
|
||||
(int)(subs[i].rm_eo - subs[i].rm_so),
|
||||
argv[optind] + subs[i].rm_so);
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/*
|
||||
- regress - main loop of regression test
|
||||
== void regress(FILE *in);
|
||||
*/
|
||||
void
|
||||
regress(in)
|
||||
FILE *in;
|
||||
{
|
||||
char inbuf[1000];
|
||||
# define MAXF 10
|
||||
char *f[MAXF];
|
||||
int nf;
|
||||
int i;
|
||||
char erbuf[100];
|
||||
size_t ne;
|
||||
char *badpat = "invalid regular expression";
|
||||
# define SHORT 10
|
||||
char *bpname = "REG_BADPAT";
|
||||
regex_t re;
|
||||
|
||||
while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
|
||||
line++;
|
||||
if (inbuf[0] == '#' || inbuf[0] == '\n')
|
||||
continue; /* NOTE CONTINUE */
|
||||
inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
|
||||
if (debug)
|
||||
fprintf(stdout, "%d:\n", line);
|
||||
nf = split(inbuf, f, MAXF, "\t\t");
|
||||
if (nf < 3) {
|
||||
fprintf(stderr, "bad input, line %d\n", line);
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < nf; i++)
|
||||
if (strcmp(f[i], "\"\"") == 0)
|
||||
f[i] = "";
|
||||
if (nf <= 3)
|
||||
f[3] = NULL;
|
||||
if (nf <= 4)
|
||||
f[4] = NULL;
|
||||
try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
|
||||
if (opt('&', f[1])) /* try with either type of RE */
|
||||
try(f[0], f[1], f[2], f[3], f[4],
|
||||
options('c', f[1]) &~ REG_EXTENDED);
|
||||
}
|
||||
|
||||
ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
|
||||
if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
|
||||
fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
|
||||
erbuf, badpat);
|
||||
status = 1;
|
||||
}
|
||||
ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT);
|
||||
if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
|
||||
ne != strlen(badpat)+1) {
|
||||
fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
|
||||
erbuf, SHORT-1, badpat);
|
||||
status = 1;
|
||||
}
|
||||
ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
|
||||
if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
|
||||
fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
|
||||
erbuf, bpname);
|
||||
status = 1;
|
||||
}
|
||||
re.re_endp = bpname;
|
||||
ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
|
||||
if (atoi(erbuf) != (int)REG_BADPAT) {
|
||||
fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
|
||||
erbuf, (long)REG_BADPAT);
|
||||
status = 1;
|
||||
} else if (ne != strlen(erbuf)+1) {
|
||||
fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
|
||||
erbuf, (long)REG_BADPAT);
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- try - try it, and report on problems
|
||||
== void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
|
||||
*/
|
||||
void
|
||||
try(f0, f1, f2, f3, f4, opts)
|
||||
char *f0;
|
||||
char *f1;
|
||||
char *f2;
|
||||
char *f3;
|
||||
char *f4;
|
||||
int opts; /* may not match f1 */
|
||||
{
|
||||
regex_t re;
|
||||
# define NSUBS 10
|
||||
regmatch_t subs[NSUBS];
|
||||
# define NSHOULD 15
|
||||
char *should[NSHOULD];
|
||||
int nshould;
|
||||
char erbuf[100];
|
||||
int err;
|
||||
int len;
|
||||
char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
|
||||
register int i;
|
||||
char *grump;
|
||||
char f0copy[1000];
|
||||
char f2copy[1000];
|
||||
|
||||
strcpy(f0copy, f0);
|
||||
re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL;
|
||||
fixstr(f0copy);
|
||||
err = regcomp(&re, f0copy, opts);
|
||||
if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
|
||||
/* unexpected error or wrong error */
|
||||
len = regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
|
||||
line, type, eprint(err), len,
|
||||
sizeof(erbuf), erbuf);
|
||||
status = 1;
|
||||
} else if (err == 0 && opt('C', f1)) {
|
||||
/* unexpected success */
|
||||
fprintf(stderr, "%d: %s should have given REG_%s\n",
|
||||
line, type, f2);
|
||||
status = 1;
|
||||
err = 1; /* so we won't try regexec */
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
regfree(&re);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(f2copy, f2);
|
||||
fixstr(f2copy);
|
||||
|
||||
if (options('e', f1)®_STARTEND) {
|
||||
if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
|
||||
fprintf(stderr, "%d: bad STARTEND syntax\n", line);
|
||||
subs[0].rm_so = strchr(f2, '(') - f2 + 1;
|
||||
subs[0].rm_eo = strchr(f2, ')') - f2;
|
||||
}
|
||||
err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
|
||||
|
||||
if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
|
||||
/* unexpected error or wrong error */
|
||||
len = regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
|
||||
line, type, eprint(err), len,
|
||||
sizeof(erbuf), erbuf);
|
||||
status = 1;
|
||||
} else if (err != 0) {
|
||||
/* nothing more to check */
|
||||
} else if (f3 == NULL) {
|
||||
/* unexpected success */
|
||||
fprintf(stderr, "%d: %s exec should have failed\n",
|
||||
line, type);
|
||||
status = 1;
|
||||
err = 1; /* just on principle */
|
||||
} else if (opts®_NOSUB) {
|
||||
/* nothing more to check */
|
||||
} else if ((grump = check(f2, subs[0], f3)) != NULL) {
|
||||
fprintf(stderr, "%d: %s %s\n", line, type, grump);
|
||||
status = 1;
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (err != 0 || f4 == NULL) {
|
||||
regfree(&re);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 1; i < NSHOULD; i++)
|
||||
should[i] = NULL;
|
||||
nshould = split(f4, should+1, NSHOULD-1, ",");
|
||||
if (nshould == 0) {
|
||||
nshould = 1;
|
||||
should[1] = "";
|
||||
}
|
||||
for (i = 1; i < NSUBS; i++) {
|
||||
grump = check(f2, subs[i], should[i]);
|
||||
if (grump != NULL) {
|
||||
fprintf(stderr, "%d: %s $%d %s\n", line,
|
||||
type, i, grump);
|
||||
status = 1;
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
regfree(&re);
|
||||
}
|
||||
|
||||
/*
|
||||
- options - pick options out of a regression-test string
|
||||
== int options(int type, char *s);
|
||||
*/
|
||||
int
|
||||
options(type, s)
|
||||
int type; /* 'c' compile, 'e' exec */
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
register int o = (type == 'c') ? copts : eopts;
|
||||
register char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
|
||||
|
||||
for (p = s; *p != '\0'; p++)
|
||||
if (strchr(legal, *p) != NULL)
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
o &= ~REG_EXTENDED;
|
||||
break;
|
||||
case 'i':
|
||||
o |= REG_ICASE;
|
||||
break;
|
||||
case 's':
|
||||
o |= REG_NOSUB;
|
||||
break;
|
||||
case 'n':
|
||||
o |= REG_NEWLINE;
|
||||
break;
|
||||
case 'm':
|
||||
o &= ~REG_EXTENDED;
|
||||
o |= REG_NOSPEC;
|
||||
break;
|
||||
case 'p':
|
||||
o |= REG_PEND;
|
||||
break;
|
||||
case '^':
|
||||
o |= REG_NOTBOL;
|
||||
break;
|
||||
case '$':
|
||||
o |= REG_NOTEOL;
|
||||
break;
|
||||
case '#':
|
||||
o |= REG_STARTEND;
|
||||
break;
|
||||
case 't': /* trace */
|
||||
o |= REG_TRACE;
|
||||
break;
|
||||
case 'l': /* force long representation */
|
||||
o |= REG_LARGE;
|
||||
break;
|
||||
case 'r': /* force backref use */
|
||||
o |= REG_BACKR;
|
||||
break;
|
||||
}
|
||||
return(o);
|
||||
}
|
||||
|
||||
/*
|
||||
- opt - is a particular option in a regression string?
|
||||
== int opt(int c, char *s);
|
||||
*/
|
||||
int /* predicate */
|
||||
opt(c, s)
|
||||
int c;
|
||||
char *s;
|
||||
{
|
||||
return(strchr(s, c) != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
- fixstr - transform magic characters in strings
|
||||
== void fixstr(register char *p);
|
||||
*/
|
||||
void
|
||||
fixstr(p)
|
||||
register char *p;
|
||||
{
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
for (; *p != '\0'; p++)
|
||||
if (*p == 'N')
|
||||
*p = '\n';
|
||||
else if (*p == 'T')
|
||||
*p = '\t';
|
||||
else if (*p == 'S')
|
||||
*p = ' ';
|
||||
else if (*p == 'Z')
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
- check - check a substring match
|
||||
== char *check(char *str, regmatch_t sub, char *should);
|
||||
*/
|
||||
char * /* NULL or complaint */
|
||||
check(str, sub, should)
|
||||
char *str;
|
||||
regmatch_t sub;
|
||||
char *should;
|
||||
{
|
||||
register int len;
|
||||
register int shlen;
|
||||
register char *p;
|
||||
static char grump[500];
|
||||
register char *at = NULL;
|
||||
|
||||
if (should != NULL && strcmp(should, "-") == 0)
|
||||
should = NULL;
|
||||
if (should != NULL && should[0] == '@') {
|
||||
at = should + 1;
|
||||
should = "";
|
||||
}
|
||||
|
||||
/* check rm_so and rm_eo for consistency */
|
||||
if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
|
||||
(sub.rm_so != -1 && sub.rm_eo == -1) ||
|
||||
(sub.rm_so != -1 && sub.rm_so < 0) ||
|
||||
(sub.rm_eo != -1 && sub.rm_eo < 0) ) {
|
||||
sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
|
||||
(long)sub.rm_eo);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
/* check for no match */
|
||||
if (sub.rm_so == -1 && should == NULL)
|
||||
return(NULL);
|
||||
if (sub.rm_so == -1)
|
||||
return("did not match");
|
||||
|
||||
/* check for in range */
|
||||
if (sub.rm_eo > strlen(str)) {
|
||||
sprintf(grump, "start %ld end %ld, past end of string",
|
||||
(long)sub.rm_so, (long)sub.rm_eo);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
len = (int)(sub.rm_eo - sub.rm_so);
|
||||
shlen = (int)strlen(should);
|
||||
p = str + sub.rm_so;
|
||||
|
||||
/* check for not supposed to match */
|
||||
if (should == NULL) {
|
||||
sprintf(grump, "matched `%.*s'", len, p);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
/* check for wrong match */
|
||||
if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
|
||||
sprintf(grump, "matched `%.*s' instead", len, p);
|
||||
return(grump);
|
||||
}
|
||||
if (shlen > 0)
|
||||
return(NULL);
|
||||
|
||||
/* check null match in right place */
|
||||
if (at == NULL)
|
||||
return(NULL);
|
||||
shlen = strlen(at);
|
||||
if (shlen == 0)
|
||||
shlen = 1; /* force check for end-of-string */
|
||||
if (strncmp(p, at, shlen) != 0) {
|
||||
sprintf(grump, "matched null at `%.20s'", p);
|
||||
return(grump);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
- eprint - convert error number to name
|
||||
== static char *eprint(int err);
|
||||
*/
|
||||
static char *
|
||||
eprint(err)
|
||||
int err;
|
||||
{
|
||||
static char epbuf[100];
|
||||
size_t len;
|
||||
|
||||
len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
|
||||
assert(len <= sizeof(epbuf));
|
||||
return(epbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
- efind - convert error name to number
|
||||
== static int efind(char *name);
|
||||
*/
|
||||
static int
|
||||
efind(name)
|
||||
char *name;
|
||||
{
|
||||
static char efbuf[100];
|
||||
size_t n;
|
||||
regex_t re;
|
||||
|
||||
sprintf(efbuf, "REG_%s", name);
|
||||
assert(strlen(efbuf) < sizeof(efbuf));
|
||||
re.re_endp = efbuf;
|
||||
(void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
|
||||
return(atoi(efbuf));
|
||||
}
|
1603
src/regex/regcomp.c
Normal file
1603
src/regex/regcomp.c
Normal file
File diff suppressed because it is too large
Load Diff
134
src/regex/regex2.h
Normal file
134
src/regex/regex2.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* First, the stuff that ends up in the outside-world include file
|
||||
= typedef off_t regoff_t;
|
||||
= typedef struct {
|
||||
= int re_magic;
|
||||
= size_t re_nsub; // number of parenthesized subexpressions
|
||||
= const char *re_endp; // end pointer for REG_PEND
|
||||
= struct re_guts *re_g; // none of your business :-)
|
||||
= } regex_t;
|
||||
= typedef struct {
|
||||
= regoff_t rm_so; // start of match
|
||||
= regoff_t rm_eo; // end of match
|
||||
= } regmatch_t;
|
||||
*/
|
||||
/*
|
||||
* internals of regex_t
|
||||
*/
|
||||
#define MAGIC1 ((('r'^0200)<<8) | 'e')
|
||||
|
||||
/*
|
||||
* The internal representation is a *strip*, a sequence of
|
||||
* operators ending with an endmarker. (Some terminology etc. is a
|
||||
* historical relic of earlier versions which used multiple strips.)
|
||||
* Certain oddities in the representation are there to permit running
|
||||
* the machinery backwards; in particular, any deviation from sequential
|
||||
* flow must be marked at both its source and its destination. Some
|
||||
* fine points:
|
||||
*
|
||||
* - OPLUS_ and O_PLUS are *inside* the loop they create.
|
||||
* - OQUEST_ and O_QUEST are *outside* the bypass they create.
|
||||
* - OCH_ and O_CH are *outside* the multi-way branch they create, while
|
||||
* OOR1 and OOR2 are respectively the end and the beginning of one of
|
||||
* the branches. Note that there is an implicit OOR2 following OCH_
|
||||
* and an implicit OOR1 preceding O_CH.
|
||||
*
|
||||
* In state representations, an operator's bit is on to signify a state
|
||||
* immediately *preceding* "execution" of that operator.
|
||||
*/
|
||||
typedef long sop; /* strip operator */
|
||||
typedef long sopno;
|
||||
#define OPRMASK 0x7c000000
|
||||
#define OPDMASK 0x03ffffff
|
||||
#define OPSHIFT (26)
|
||||
#define OP(n) ((n)&OPRMASK)
|
||||
#define OPND(n) ((n)&OPDMASK)
|
||||
#define SOP(op, opnd) ((op)|(opnd))
|
||||
/* operators meaning operand */
|
||||
/* (back, fwd are offsets) */
|
||||
#define OEND (1<<OPSHIFT) /* endmarker - */
|
||||
#define OCHAR (2<<OPSHIFT) /* character unsigned char */
|
||||
#define OBOL (3<<OPSHIFT) /* left anchor - */
|
||||
#define OEOL (4<<OPSHIFT) /* right anchor - */
|
||||
#define OANY (5<<OPSHIFT) /* . - */
|
||||
#define OANYOF (6<<OPSHIFT) /* [...] set number */
|
||||
#define OBACK_ (7<<OPSHIFT) /* begin \d paren number */
|
||||
#define O_BACK (8<<OPSHIFT) /* end \d paren number */
|
||||
#define OPLUS_ (9<<OPSHIFT) /* + prefix fwd to suffix */
|
||||
#define O_PLUS (10<<OPSHIFT) /* + suffix back to prefix */
|
||||
#define OQUEST_ (11<<OPSHIFT) /* ? prefix fwd to suffix */
|
||||
#define O_QUEST (12<<OPSHIFT) /* ? suffix back to prefix */
|
||||
#define OLPAREN (13<<OPSHIFT) /* ( fwd to ) */
|
||||
#define ORPAREN (14<<OPSHIFT) /* ) back to ( */
|
||||
#define OCH_ (15<<OPSHIFT) /* begin choice fwd to OOR2 */
|
||||
#define OOR1 (16<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */
|
||||
#define OOR2 (17<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */
|
||||
#define O_CH (18<<OPSHIFT) /* end choice back to OOR1 */
|
||||
#define OBOW (19<<OPSHIFT) /* begin word - */
|
||||
#define OEOW (20<<OPSHIFT) /* end word - */
|
||||
|
||||
/*
|
||||
* Structure for [] character-set representation. Character sets are
|
||||
* done as bit vectors, grouped 8 to a byte vector for compactness.
|
||||
* The individual set therefore has both a pointer to the byte vector
|
||||
* and a mask to pick out the relevant bit of each byte. A hash code
|
||||
* simplifies testing whether two sets could be identical.
|
||||
*
|
||||
* This will get trickier for multicharacter collating elements. As
|
||||
* preliminary hooks for dealing with such things, we also carry along
|
||||
* a string of multi-character elements, and decide the size of the
|
||||
* vectors at run time.
|
||||
*/
|
||||
typedef struct {
|
||||
uch *ptr; /* -> uch [csetsize] */
|
||||
uch mask; /* bit within array */
|
||||
uch hash; /* hash code */
|
||||
size_t smultis;
|
||||
char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */
|
||||
} cset;
|
||||
/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
|
||||
#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
|
||||
#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
|
||||
#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask)
|
||||
#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */
|
||||
#define MCsub(p, cs, cp) mcsub(p, cs, cp)
|
||||
#define MCin(p, cs, cp) mcin(p, cs, cp)
|
||||
|
||||
/* stuff for character categories */
|
||||
typedef unsigned char cat_t;
|
||||
|
||||
/*
|
||||
* main compiled-expression structure
|
||||
*/
|
||||
struct re_guts {
|
||||
int magic;
|
||||
# define MAGIC2 ((('R'^0200)<<8)|'E')
|
||||
sop *strip; /* malloced area for strip */
|
||||
int csetsize; /* number of bits in a cset vector */
|
||||
int ncsets; /* number of csets in use */
|
||||
cset *sets; /* -> cset [ncsets] */
|
||||
uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */
|
||||
int cflags; /* copy of regcomp() cflags argument */
|
||||
sopno nstates; /* = number of sops */
|
||||
sopno firststate; /* the initial OEND (normally 0) */
|
||||
sopno laststate; /* the final OEND */
|
||||
int iflags; /* internal flags */
|
||||
# define USEBOL 01 /* used ^ */
|
||||
# define USEEOL 02 /* used $ */
|
||||
# define BAD 04 /* something wrong */
|
||||
int nbol; /* number of ^ used */
|
||||
int neol; /* number of $ used */
|
||||
int ncategories; /* how many character categories */
|
||||
cat_t *categories; /* ->catspace[-CHAR_MIN] */
|
||||
char *must; /* match must contain this string */
|
||||
int mlen; /* length of must */
|
||||
size_t nsub; /* copy of re_nsub */
|
||||
int backrefs; /* does it use back references? */
|
||||
sopno nplus; /* how deep does it nest +s? */
|
||||
/* catspace must be last */
|
||||
cat_t catspace[1]; /* actually [NC] */
|
||||
};
|
||||
|
||||
/* misc utilities */
|
||||
#define OUT (CHAR_MAX+1) /* a non-character value */
|
||||
#define ISWORD(c) (isalnum(c) || (c) == '_')
|
316
src/regex/split.c
Normal file
316
src/regex/split.c
Normal file
@ -0,0 +1,316 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
- split - divide a string into fields, like awk split()
|
||||
= int split(char *string, char *fields[], int nfields, char *sep);
|
||||
*/
|
||||
int /* number of fields, including overflow */
|
||||
split(string, fields, nfields, sep)
|
||||
char *string;
|
||||
char *fields[]; /* list is not NULL-terminated */
|
||||
int nfields; /* number of entries available in fields[] */
|
||||
char *sep; /* "" white, "c" single char, "ab" [ab]+ */
|
||||
{
|
||||
register char *p = string;
|
||||
register char c; /* latest character */
|
||||
register char sepc = sep[0];
|
||||
register char sepc2;
|
||||
register int fn;
|
||||
register char **fp = fields;
|
||||
register char *sepp;
|
||||
register int trimtrail;
|
||||
|
||||
/* white space */
|
||||
if (sepc == '\0') {
|
||||
while ((c = *p++) == ' ' || c == '\t')
|
||||
continue;
|
||||
p--;
|
||||
trimtrail = 1;
|
||||
sep = " \t"; /* note, code below knows this is 2 long */
|
||||
sepc = ' ';
|
||||
} else
|
||||
trimtrail = 0;
|
||||
sepc2 = sep[1]; /* now we can safely pick this up */
|
||||
|
||||
/* catch empties */
|
||||
if (*p == '\0')
|
||||
return(0);
|
||||
|
||||
/* single separator */
|
||||
if (sepc2 == '\0') {
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
*fp++ = p;
|
||||
fn--;
|
||||
if (fn == 0)
|
||||
break;
|
||||
while ((c = *p++) != sepc)
|
||||
if (c == '\0')
|
||||
return(nfields - fn);
|
||||
*(p-1) = '\0';
|
||||
}
|
||||
/* we have overflowed the fields vector -- just count them */
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
while ((c = *p++) != sepc)
|
||||
if (c == '\0')
|
||||
return(fn);
|
||||
fn++;
|
||||
}
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
/* two separators */
|
||||
if (sep[2] == '\0') {
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
*fp++ = p;
|
||||
fn--;
|
||||
while ((c = *p++) != sepc && c != sepc2)
|
||||
if (c == '\0') {
|
||||
if (trimtrail && **(fp-1) == '\0')
|
||||
fn++;
|
||||
return(nfields - fn);
|
||||
}
|
||||
if (fn == 0)
|
||||
break;
|
||||
*(p-1) = '\0';
|
||||
while ((c = *p++) == sepc || c == sepc2)
|
||||
continue;
|
||||
p--;
|
||||
}
|
||||
/* we have overflowed the fields vector -- just count them */
|
||||
fn = nfields;
|
||||
while (c != '\0') {
|
||||
while ((c = *p++) == sepc || c == sepc2)
|
||||
continue;
|
||||
p--;
|
||||
fn++;
|
||||
while ((c = *p++) != '\0' && c != sepc && c != sepc2)
|
||||
continue;
|
||||
}
|
||||
/* might have to trim trailing white space */
|
||||
if (trimtrail) {
|
||||
p--;
|
||||
while ((c = *--p) == sepc || c == sepc2)
|
||||
continue;
|
||||
p++;
|
||||
if (*p != '\0') {
|
||||
if (fn == nfields+1)
|
||||
*p = '\0';
|
||||
fn--;
|
||||
}
|
||||
}
|
||||
return(fn);
|
||||
}
|
||||
|
||||
/* n separators */
|
||||
fn = 0;
|
||||
for (;;) {
|
||||
if (fn < nfields)
|
||||
*fp++ = p;
|
||||
fn++;
|
||||
for (;;) {
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
return(fn);
|
||||
sepp = sep;
|
||||
while ((sepc = *sepp++) != '\0' && sepc != c)
|
||||
continue;
|
||||
if (sepc != '\0') /* it was a separator */
|
||||
break;
|
||||
}
|
||||
if (fn < nfields)
|
||||
*(p-1) = '\0';
|
||||
for (;;) {
|
||||
c = *p++;
|
||||
sepp = sep;
|
||||
while ((sepc = *sepp++) != '\0' && sepc != c)
|
||||
continue;
|
||||
if (sepc == '\0') /* it wasn't a separator */
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
#ifdef TEST_SPLIT
|
||||
|
||||
|
||||
/*
|
||||
* test program
|
||||
* pgm runs regression
|
||||
* pgm sep splits stdin lines by sep
|
||||
* pgm str sep splits str by sep
|
||||
* pgm str sep n splits str by sep n times
|
||||
*/
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
char buf[512];
|
||||
register int n;
|
||||
# define MNF 10
|
||||
char *fields[MNF];
|
||||
|
||||
if (argc > 4)
|
||||
for (n = atoi(argv[3]); n > 0; n--) {
|
||||
(void) strcpy(buf, argv[1]);
|
||||
}
|
||||
else if (argc > 3)
|
||||
for (n = atoi(argv[3]); n > 0; n--) {
|
||||
(void) strcpy(buf, argv[1]);
|
||||
(void) split(buf, fields, MNF, argv[2]);
|
||||
}
|
||||
else if (argc > 2)
|
||||
dosplit(argv[1], argv[2]);
|
||||
else if (argc > 1)
|
||||
while (fgets(buf, sizeof(buf), stdin) != NULL) {
|
||||
buf[strlen(buf)-1] = '\0'; /* stomp newline */
|
||||
dosplit(buf, argv[1]);
|
||||
}
|
||||
else
|
||||
regress();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
dosplit(string, seps)
|
||||
char *string;
|
||||
char *seps;
|
||||
{
|
||||
# define NF 5
|
||||
char *fields[NF];
|
||||
register int nf;
|
||||
|
||||
nf = split(string, fields, NF, seps);
|
||||
print(nf, NF, fields);
|
||||
}
|
||||
|
||||
print(nf, nfp, fields)
|
||||
int nf;
|
||||
int nfp;
|
||||
char *fields[];
|
||||
{
|
||||
register int fn;
|
||||
register int bound;
|
||||
|
||||
bound = (nf > nfp) ? nfp : nf;
|
||||
printf("%d:\t", nf);
|
||||
for (fn = 0; fn < bound; fn++)
|
||||
printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
|
||||
}
|
||||
|
||||
#define RNF 5 /* some table entries know this */
|
||||
struct {
|
||||
char *str;
|
||||
char *seps;
|
||||
int nf;
|
||||
char *fi[RNF];
|
||||
} tests[] = {
|
||||
"", " ", 0, { "" },
|
||||
" ", " ", 2, { "", "" },
|
||||
"x", " ", 1, { "x" },
|
||||
"xy", " ", 1, { "xy" },
|
||||
"x y", " ", 2, { "x", "y" },
|
||||
"abc def g ", " ", 5, { "abc", "def", "", "g", "" },
|
||||
" a bcd", " ", 4, { "", "", "a", "bcd" },
|
||||
"a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
|
||||
" a b c d ", " ", 6, { "", "a", "b", "c", "d " },
|
||||
|
||||
"", " _", 0, { "" },
|
||||
" ", " _", 2, { "", "" },
|
||||
"x", " _", 1, { "x" },
|
||||
"x y", " _", 2, { "x", "y" },
|
||||
"ab _ cd", " _", 2, { "ab", "cd" },
|
||||
" a_b c ", " _", 5, { "", "a", "b", "c", "" },
|
||||
"a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" },
|
||||
" a b c d ", " _", 6, { "", "a", "b", "c", "d " },
|
||||
|
||||
"", " _~", 0, { "" },
|
||||
" ", " _~", 2, { "", "" },
|
||||
"x", " _~", 1, { "x" },
|
||||
"x y", " _~", 2, { "x", "y" },
|
||||
"ab _~ cd", " _~", 2, { "ab", "cd" },
|
||||
" a_b c~", " _~", 5, { "", "a", "b", "c", "" },
|
||||
"a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" },
|
||||
"~a b c d ", " _~", 6, { "", "a", "b", "c", "d " },
|
||||
|
||||
"", " _~-", 0, { "" },
|
||||
" ", " _~-", 2, { "", "" },
|
||||
"x", " _~-", 1, { "x" },
|
||||
"x y", " _~-", 2, { "x", "y" },
|
||||
"ab _~- cd", " _~-", 2, { "ab", "cd" },
|
||||
" a_b c~", " _~-", 5, { "", "a", "b", "c", "" },
|
||||
"a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" },
|
||||
"~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " },
|
||||
|
||||
"", " ", 0, { "" },
|
||||
" ", " ", 2, { "", "" },
|
||||
"x", " ", 1, { "x" },
|
||||
"xy", " ", 1, { "xy" },
|
||||
"x y", " ", 2, { "x", "y" },
|
||||
"abc def g ", " ", 4, { "abc", "def", "g", "" },
|
||||
" a bcd", " ", 3, { "", "a", "bcd" },
|
||||
"a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
|
||||
" a b c d ", " ", 6, { "", "a", "b", "c", "d " },
|
||||
|
||||
"", "", 0, { "" },
|
||||
" ", "", 0, { "" },
|
||||
"x", "", 1, { "x" },
|
||||
"xy", "", 1, { "xy" },
|
||||
"x y", "", 2, { "x", "y" },
|
||||
"abc def g ", "", 3, { "abc", "def", "g" },
|
||||
"\t a bcd", "", 2, { "a", "bcd" },
|
||||
" a \tb\t c ", "", 3, { "a", "b", "c" },
|
||||
"a b c d e ", "", 5, { "a", "b", "c", "d", "e" },
|
||||
"a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" },
|
||||
" a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " },
|
||||
|
||||
NULL, NULL, 0, { NULL },
|
||||
};
|
||||
|
||||
regress()
|
||||
{
|
||||
char buf[512];
|
||||
register int n;
|
||||
char *fields[RNF+1];
|
||||
register int nf;
|
||||
register int i;
|
||||
register int printit;
|
||||
register char *f;
|
||||
|
||||
for (n = 0; tests[n].str != NULL; n++) {
|
||||
(void) strcpy(buf, tests[n].str);
|
||||
fields[RNF] = NULL;
|
||||
nf = split(buf, fields, RNF, tests[n].seps);
|
||||
printit = 0;
|
||||
if (nf != tests[n].nf) {
|
||||
printf("split `%s' by `%s' gave %d fields, not %d\n",
|
||||
tests[n].str, tests[n].seps, nf, tests[n].nf);
|
||||
printit = 1;
|
||||
} else if (fields[RNF] != NULL) {
|
||||
printf("split() went beyond array end\n");
|
||||
printit = 1;
|
||||
} else {
|
||||
for (i = 0; i < nf && i < RNF; i++) {
|
||||
f = fields[i];
|
||||
if (f == NULL)
|
||||
f = "(NULL)";
|
||||
if (strcmp(f, tests[n].fi[i]) != 0) {
|
||||
printf("split `%s' by `%s', field %d is `%s', not `%s'\n",
|
||||
tests[n].str, tests[n].seps,
|
||||
i, fields[i], tests[n].fi[i]);
|
||||
printit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (printit)
|
||||
print(nf, RNF, fields);
|
||||
}
|
||||
}
|
||||
#endif
|
22
src/regex/utils.h
Normal file
22
src/regex/utils.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* utility definitions */
|
||||
#ifdef _POSIX2_RE_DUP_MAX
|
||||
#define DUPMAX _POSIX2_RE_DUP_MAX
|
||||
#else
|
||||
#define DUPMAX 255
|
||||
#endif
|
||||
#define INFINITY (DUPMAX + 1)
|
||||
#define NC (CHAR_MAX - CHAR_MIN + 1)
|
||||
typedef unsigned char uch;
|
||||
|
||||
/* switch off assertions (if not already off) if no REDEBUG */
|
||||
#ifndef REDEBUG
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG /* no assertions please */
|
||||
#endif
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
/* for old systems with bcopy() but no memmove() */
|
||||
#ifdef USEBCOPY
|
||||
#define memmove(d, s, c) bcopy(s, d, c)
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user