b.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "awk.def"
#include "stdio.h"
#include "awk.h"
extern NODE *op2();
extern struct fa *cgotofn();
#define MAXLIN 256
#define NCHARS 128
#define NSTATES 256
#define type(v) v->nobj
#define left(v) v->narg[0]
#define right(v) v->narg[1]
#define parent(v) v->nnext
#define LEAF case CCL: case NCCL: case CHAR: case DOT:
#define UNARY case FINAL: case STAR: case PLUS: case QUEST:
/*
* encoding in tree NODEs:
* leaf (CCL, NCCL, CHAR, DOT): left is index,
* right contains value or pointer to value
* unary (FINAL, STAR, PLUS, QUEST): left is child, right is null
* binary (CAT, OR): left and right are children
* parent contains pointer to parent
*/
struct fa {
union {
ccl_chars_t s;
int h;
} cc;
#define MLCMPLT(m1, l1, m2, l2) ((m1 != m2 &&\
(int)m1 < (int)m2) ||\
(m1 == m2 && (int)l1 < (int)l2))
#define MLCMPLE(m1, l1, m2, l2) ((m1 != m2 &&\
(int)m1 <= (int)m2) ||\
(m1 == m2 && (int)l1 <= (int)l2))
#define MLCMPGT(m1, l1, m2, l2) ((m1 != m2 &&\
(int)m1 > (int)m2) ||\
(m1 == m2 && (int)l1 > (int)l2))
#define MAX_CODESET 3
struct fa *st;
};
int *state[NSTATES];
int *foll[MAXLIN];
int setvec[MAXLIN];
NODE *point[MAXLIN];
int setcnt;
int line;
static int ccln_member();
static int insert_table();
static int delete_table();
#ifdef DEBUG
#define ddump_table(t, s) dump_table(t, s)
#else
#define ddump_table(t, s)
#endif
struct fa *
makedfa(p) /* returns dfa for tree pointed to by p */
NODE *p;
{
NODE *p1;
struct fa *fap;
p1 = op2(CAT, op2(STAR, op2(DOT, (NODE *) 0,
(NODE *) 0), (NODE *) 0), p);
/* put DOT STAR in front of reg. exp. */
p1 = op2(FINAL, p1, (NODE *) 0); /* install FINAL NODE */
line = 0;
penter(p1); /* enter parent pointers and leaf indices */
point[line] = p1; /* FINAL NODE */
setvec[0] = 1; /* for initial DOT STAR */
cfoll(p1); /* set up follow sets */
fap = cgotofn();
freetr(p1); /* add this when alloc works */
return (fap);
}
penter(p) /* set up parent pointers and leaf indices */
NODE *p;
{
switch (type(p)) {
LEAF
left(p) = (NODE *)line;
point[line++] = p;
break;
UNARY
penter(left(p));
parent(left(p)) = p;
break;
case CAT:
case OR:
penter(left(p));
penter(right(p));
parent(left(p)) = p;
parent(right(p)) = p;
break;
default:
error(FATAL, "unknown type %d in penter\n", type(p));
break;
}
}
freetr(p) /* free parse tree and follow sets */
NODE *p;
{
switch (type(p)) {
LEAF
xfree(foll[(int)left(p)]);
xfree(p);
break;
UNARY
freetr(left(p));
xfree(p);
break;
case CAT:
case OR:
freetr(left(p));
freetr(right(p));
xfree(p);
break;
default:
error(FATAL, "unknown type %d in freetr", type(p));
break;
}
}
ccl_chars_t *
cclenter(p)
register wchar_t *p;
{
register int i, cn;
register wchar_t c, pc;
register wchar_t *op;
register ccl_chars_t *new;
ccl_chars_t chars[MAXLIN];
op = p;
i = 0;
while ((c = *p++) != 0) {
if (c == '-' && i > 0) {
if (*p != 0) {
/*
* If there are not in same code set, the
* class should be ignore (make two independent
* characters)!
*/
c = *p++;
cn = wcsetno(pc);
if (cn != wcsetno(c) || pc > c)
goto char_array;
i = insert_table(chars, i, cn, pc, cn, c);
continue;
}
}
char_array:
if (i >= MAXLIN)
overflo();
cn = wcsetno(c);
i = insert_table(chars, i, cn, c, cn, c);
pc = c;
}
dprintf("cclenter: in = |%ws|, ", op, NULL, NULL);
xfree(op);
i = (i + 1) * sizeof (ccl_chars_t);
if ((new = (ccl_chars_t *)malloc(i)) == NULL)
error(FATAL, "out of space in cclenter on %s", op);
(void) memcpy((char *)new, (char *)chars, i);
ddump_table(chars, i / 4);
return (new);
}
overflo()
{
error(FATAL, "regular expression too long\n");
}
cfoll(v) /* enter follow set of each leaf of vertex v into foll[leaf] */
register NODE *v;
{
register i;
int prev;
int *add();
switch (type(v)) {
LEAF
setcnt = 0;
for (i = 1; i <= line; i++)
setvec[i] = 0;
follow(v);
foll[(int)left(v)] = add(setcnt);
break;
UNARY
cfoll(left(v));
break;
case CAT:
case OR:
cfoll(left(v));
cfoll(right(v));
break;
default:
error(FATAL, "unknown type %d in cfoll", type(v));
}
}
first(p) /* collects initially active leaves of p into setvec */
register NODE *p;
/* returns 0 or 1 depending on whether p matches empty string */
{
register b;
switch (type(p)) {
LEAF
if (setvec[(int)left(p)] != 1) {
setvec[(int)left(p)] = 1;
setcnt++;
}
if (type(p) == CCL &&
(*(ccl_chars_t *)right(p)).cc_cs == (wchar_t)0x0)
return (0); /* empty CCL */
else return (1);
case FINAL:
case PLUS:
if (first(left(p)) == 0)
return (0);
return (1);
case STAR:
case QUEST:
first(left(p));
return (0);
case CAT:
if (first(left(p)) == 0 && first(right(p)) == 0)
return (0);
return (1);
case OR:
b = first(right(p));
if (first(left(p)) == 0 || b == 0)
return (0);
return (1);
}
error(FATAL, "unknown type %d in first\n", type(p));
return (-1);
}
follow(v)
NODE *v; /* collects leaves that can follow v into setvec */
{
NODE *p;
if (type(v) == FINAL)
return;
p = parent(v);
switch (type(p)) {
case STAR:
case PLUS: first(v);
follow(p);
return;
case OR:
case QUEST: follow(p);
return;
case CAT: if (v == left(p)) { /* v is left child of p */
if (first(right(p)) == 0) {
follow(p);
return;
}
} else /* v is right child */
follow(p);
return;
case FINAL: if (setvec[line] != 1) {
setvec[line] = 1;
setcnt++;
}
return;
}
}
/*
* There are three type of functions for checking member ship. Because I have
* been changed structure of CCL tables. And some CCL tables end up with NULLs
* but someone has length and will includes NULLs in table as one of data.
* Please note, CCL table which has a length data and data will include NULLs,
* it only used within a this source file("b.c").
*/
ccl_member(ns, cs, ne, ce, s) /* is cs thru ce in s? */
register int ns;
register wchar_t cs;
register int ne;
register wchar_t ce;
register ccl_chars_t *s;
{
/*
* The specified range(cs, ce) must be beside the range between
* s->cc_start and s->cc_end to determine member.
*/
while (s->cc_cs || s->cc_ce) {
if (MLCMPLE(s->cc_ns, s->cc_cs, ns, cs) &&
MLCMPLE(ne, ce, s->cc_ne, s->cc_ce))
return (1);
s++;
}
return (0);
}
static
ccln_member(ns, cs, ne, ce, s, n) /* is cs thru ce in s? */
register int ns;
register wchar_t cs;
register int ne;
register wchar_t ce;
register ccl_chars_t *s;
register int n;
{
/*
* The specified range(cs, ce) must be beside the range between
* s->cc_start and s->cc_end to determine member.
*/
while (n-- > 0) {
if (MLCMPLE(s->cc_ns, s->cc_cs, ns, cs) &&
MLCMPLE(ne, ce, s->cc_ne, s->cc_ce))
return (1);
s++;
}
return (0);
}
member(c, s) /* is c in s? */
register wchar_t c, *s;
{
while (*s)
if (c == *s++)
return (1);
return (0);
}
notin(array, n, prev) /* is setvec in array[0] thru array[n]? */
int **array;
int *prev; {
register i, j;
int *ptr;
for (i = 0; i <= n; i++) {
ptr = array[i];
if (*ptr == setcnt) {
for (j = 0; j < setcnt; j++)
if (setvec[*(++ptr)] != 1) goto nxt;
*prev = i;
return (0);
}
nxt: /* dummy */;
}
return (1);
}
int *add(n) { /* remember setvec */
int *ptr, *p;
register i;
if ((p = ptr = (int *)malloc((n+1)*sizeof (int))) == NULL)
overflo();
*ptr = n;
dprintf("add(%d)\n", n, NULL, NULL);
for (i = 1; i <= line; i++)
if (setvec[i] == 1) {
*(++ptr) = i;
dprintf(" ptr = %o, *ptr = %d, i = %d\n", ptr, *ptr, i);
}
dprintf("\n", NULL, NULL, NULL);
return (p);
}
struct fa *
cgotofn()
{
register i, k;
register int *ptr;
register int ns, ne;
register wchar_t cs, ce;
register ccl_chars_t *p;
register NODE *cp;
int j, n, s, ind, numtrans;
int finflg;
int curpos, num, prev;
struct fa *where[NSTATES];
struct {
ccl_chars_t cc;
int n;
} fatab[257];
register struct fa *pfa;
char index[MAXLIN];
char iposns[MAXLIN];
int sposns[MAXLIN];
int spmax, spinit;
ccl_chars_t symbol[NCHARS];
ccl_chars_t isyms[NCHARS];
ccl_chars_t ssyms[NCHARS];
int ssmax, symax, ismax, ssinit;
wchar_t hat;
int hatcn;
for (i = 0; i <= line; i++) index[i] = iposns[i] = setvec[i] = 0;
isyms[0].cc_cs = isyms[0].cc_ce = (wchar_t)0x0;
for (i = 0; i < NCHARS; i++)
isyms[i] = symbol[i] = ssyms[i] = isyms[0];
symax = 0;
setcnt = 0;
/* compute initial positions and symbols of state 0 */
ismax = 0;
ssmax = 0;
ptr = state[0] = foll[0];
spinit = *ptr;
hat = HAT;
hatcn = wcsetno(hat);
for (i = 0; i < spinit; i++) {
curpos = *(++ptr);
sposns[i] = curpos;
iposns[curpos] = 1;
cp = point[curpos];
dprintf("i= %d, spinit = %d, curpos = %d\n", i, spinit, curpos);
switch (type(cp)) {
case CHAR:
k = (int)right(cp);
ns = wcsetno(k);
if (! ccln_member(ns, k, ns, k,
isyms, ismax)) {
ismax = insert_table(isyms, ismax,
ns, k, ns, k);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = k;
ssyms[ssmax].cc_ne = ns;
ssyms[ssmax++].cc_ce = k;
break;
case DOT:
cs = WC_VERY_SMALL;
ns = 0;
ce = HAT - 1;
ne = hatcn;
if (! ccln_member(ns, cs, ne, ce,
isyms, ismax)) {
ismax = insert_table(isyms, ismax,
ns, cs, ne, ce);
}
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_ce = ce;
ssyms[ssmax++].cc_ne = ne;
cs = HAT + 1;
ns = hatcn;
ce = WC_VERY_LARGE;
ne = MAX_CODESET;
if (! ccln_member(ns, cs, ne, ce,
isyms, ismax)) {
ismax = insert_table(isyms, ismax,
ns, cs, ne, ce);
}
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_ce = ce;
ssyms[ssmax++].cc_ne = ne;
break;
case CCL:
cs = HAT;
ns = hatcn;
for (p = (ccl_chars_t *)right(cp);
p->cc_cs; p++) {
if ((p->cc_ns != ns ||\
p->cc_cs != cs) &&\
!ccln_member(p->cc_ns, p->cc_cs,
p->cc_ne, p->cc_ce, isyms, ismax)) {
ismax = insert_table(isyms,
ismax, p->cc_ns, p->cc_cs, p->cc_ne, p->cc_ce);
}
ssyms[ssmax++] = *p;
}
break;
case NCCL:
ns = 0;
cs = WC_VERY_SMALL;
for (p = (ccl_chars_t *)right(cp);
p->cc_cs; p++) {
if ((ns != hatcn || p->cc_cs != HAT) &&
! ccln_member(ns, cs,
p->cc_ns, p->cc_cs-1,
isyms, ismax)) {
ismax = insert_table(isyms,
ismax,
ns, cs,
p->cc_ns,
p->cc_cs-1);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ne = p->cc_ns;
ssyms[ssmax++].cc_ce = p->cc_cs-1;
if (p->cc_ce == (wchar_t)0x0) {
ns = p->cc_ns;
cs = p->cc_cs + 1;
} else {
ns = p->cc_ne;
cs = p->cc_ce + 1;
}
}
if ((ns != hatcn || cs != HAT) &&
! ccln_member(ns, cs,
MAX_CODESET, WC_VERY_LARGE,
isyms, ismax)) {
ismax = insert_table(isyms, ismax,
ns, cs, MAX_CODESET,
WC_VERY_LARGE);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ne = MAX_CODESET;
ssyms[ssmax++].cc_ce = WC_VERY_LARGE;
break;
}
}
ssinit = ssmax;
symax = 0;
n = 0;
for (s = 0; s <= n; s++) {
dprintf("s = %d\n", s, NULL, NULL);
ind = 0;
numtrans = 0;
finflg = 0;
if (*(state[s] + *state[s]) == line) { /* s final? */
finflg = 1;
goto tenter;
}
spmax = spinit;
ssmax = ssinit;
ptr = state[s];
num = *ptr;
for (i = 0; i < num; i++) {
curpos = *(++ptr);
if (iposns[curpos] != 1 && index[curpos] != 1) {
index[curpos] = 1;
sposns[spmax++] = curpos;
}
cp = point[curpos];
switch (type(cp)) {
case CHAR:
k = (int)right(cp);
ns = wcsetno(k);
if (! ccln_member(ns, k, ns, k,
isyms, ismax) &&
! ccln_member(ns, k, ns, k,
symbol, symax)) {
symax = insert_table(symbol,
symax,
ns, k,
ns, k);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = k;
ssyms[ssmax].cc_ne = ns;
ssyms[ssmax++].cc_ce = k;
break;
case DOT:
cs = WC_VERY_SMALL;
ns = 0;
ce = HAT - 1;
ne = hatcn;
if (! ccln_member(ns, cs, ne, ce,
isyms, ismax) &&
! ccln_member(ns, cs, ne, ce,
symbol, symax)) {
symax = insert_table(symbol,
symax,
ns, cs,
ne, ce);
}
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_ce = ce;
ssyms[ssmax++].cc_ne = ne;
cs = HAT + 1;
ns = hatcn;
ce = WC_VERY_LARGE;
ne = MAX_CODESET;
if (! ccln_member(ns, cs, ne, ce,
isyms, ismax) &&
! ccln_member(ns, cs, ne, ce,
symbol, symax)) {
symax = insert_table(symbol,
symax,
ns, cs,
ne, ce);
}
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_ce = ce;
ssyms[ssmax++].cc_ne = ne;
break;
case CCL:
cs = HAT;
ns = hatcn;
for (p = (ccl_chars_t *)right(cp);
p->cc_cs; p++) {
if ((p->cc_ns != ns ||
p->cc_cs != cs) &&
! ccln_member(p->cc_ns,
p->cc_cs, p->cc_ne,
p->cc_ce, isyms, ismax) &&
!ccln_member(p->cc_ns, p->cc_cs,
p->cc_ne, p->cc_ce, symbol,
symax)) {
symax = insert_table(
symbol, symax, p->cc_ns,
p->cc_cs, p->cc_ne, p->cc_ce);
}
ssyms[ssmax++] = *p;
}
break;
case NCCL:
ns = 0;
cs = WC_VERY_SMALL;
for (p = (ccl_chars_t *)right(cp); p->cc_cs; p++) {
if ((p->cc_ns != hatcn || p->cc_cs != HAT) &&
! ccln_member(ns, cs, p->cc_ns,
p->cc_cs-1, isyms, ismax) &&
! ccln_member(ns, cs, p->cc_ns,
p->cc_cs-1, symbol, symax)) {
symax = insert_table(symbol,
symax, ns, cs, p->cc_ns, p->cc_cs-1);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ne = p->cc_ns;
ssyms[ssmax++].cc_ce
= p->cc_cs-1;
if (p->cc_ce == (wchar_t)0x0) {
ns = p->cc_ns;
cs = p->cc_cs + 1;
} else {
ns = p->cc_ne;
cs = p->cc_ce + 1;
}
}
if ((ns != hatcn || cs != HAT) && ! ccln_member(ns, cs,
MAX_CODESET, WC_VERY_LARGE, isyms, ismax) &&
! ccln_member(ns, cs, MAX_CODESET,
WC_VERY_LARGE, symbol, symax)) {
symax = insert_table(symbol, symax, ns, cs,
MAX_CODESET,
WC_VERY_LARGE);
}
ssyms[ssmax].cc_ns = ns;
ssyms[ssmax].cc_cs = cs;
ssyms[ssmax].cc_ne = MAX_CODESET;
ssyms[ssmax++].cc_ce = WC_VERY_LARGE;
break;
}
}
for (j = 0; j < ssmax; j++) { /* nextstate(s, ssyms[j]) */
ns = ssyms[j].cc_ns;
cs = ssyms[j].cc_cs;
ne = ssyms[j].cc_ne;
ce = ssyms[j].cc_ce;
dprintf("j = %d, cs = %o, ce = %o\n", j, cs, ce);
symax = delete_table(symbol, symax, ns, cs, ne, ce);
setcnt = 0;
for (k = 0; k <= line; k++) setvec[k] = 0;
for (i = 0; i < spmax; i++) {
index[sposns[i]] = 0;
cp = point[sposns[i]];
if ((k = type(cp)) != FINAL) {
if (k == CHAR && ns == ne && cs == ce &&
cs == (int)right(cp) ||
k == DOT || k == CCL &&
ccl_member(ns, cs, ne, ce,
(ccl_chars_t *)right(cp)) ||
k == NCCL &&
!ccl_member(ns, cs, ne, ce,
(ccl_chars_t *)right(cp))) {
ptr = foll[sposns[i]];
num = *ptr;
for (k = 0; k < num; k++) {
if (setvec[*(++ptr)] != 1 &&
iposns[*ptr] != 1) {
setvec[*ptr] = 1;
setcnt++;
}
}
}
}
} /* end nextstate */
if (notin(state, n, &prev)) {
if (n >= NSTATES - 1) {
printf("cgotofn: notin; state = %d, n = %d\n", state, n, NULL);
overflo();
}
state[++n] = add(setcnt);
dprintf(" delta(%d,[%o,%o])",
s, cs, ce);
dprintf(" = %d, ind = %d\n", n, ind+1, NULL);
fatab[++ind].cc.cc_ns = ns;
fatab[ind].cc.cc_cs = cs;
fatab[ind].cc.cc_ne = ne;
fatab[ind].cc.cc_ce = ce;
fatab[ind].n = n;
numtrans++;
} else {
if (prev != 0) {
dprintf(" delta(%d,[%o,%o])",
s, cs, ce);
dprintf("= %d, ind = %d\n",
prev, ind+1, NULL);
fatab[++ind].cc.cc_ns = ns;
fatab[ind].cc.cc_cs = cs;
fatab[ind].cc.cc_ne = ne;
fatab[ind].cc.cc_ce = ce;
fatab[ind].n = prev;
numtrans++;
}
}
}
tenter:
if ((pfa = (struct fa *)malloc((numtrans + 1)
* sizeof (struct fa))) == NULL)
overflo();
where[s] = pfa;
if (finflg)
pfa->cc.h = -1; /* s is a final state */
else
pfa->cc.h = numtrans;
pfa->st = 0;
for (i = 1, pfa += 1; i <= numtrans; i++, pfa++) {
pfa->cc.s = fatab[i].cc;
pfa->st = (struct fa *)fatab[i].n;
}
}
for (i = 0; i <= n; i++) {
if (i != 0) /* state[0] is freed later in freetr() */
xfree(state[i]); /* free state[i] */
pfa = where[i];
pfa->st = where[0];
dprintf("state %d: (%o)\n", i, pfa, NULL);
dprintf(" numtrans = %d, default = %o\n",
pfa->cc.h, pfa->st, NULL);
for (k = 1; k <= pfa->cc.h; k++) {
(pfa+k)->st = where[(int)(pfa+k)->st];
dprintf(" char = [%o,%o], nextstate = %o\n",
(pfa+k)->cc.s.cc_cs, (pfa+k)->cc.s.cc_ce,
(pfa+k)->st);
}
}
pfa = where[0];
if ((num = pfa->cc.h) < 0)
return (where[0]);
for (pfa += num; num; num--, pfa--)
if (pfa->cc.s.cc_ns == hatcn && pfa->cc.s.cc_cs == HAT) {
return (pfa->st);
}
return (where[0]);
}
/*
* Insert CCL entry to CCL table with maintain optimized order.
*/
static int
insert_table(table_base, table_size, ns, cs, ne, ce)
ccl_chars_t *table_base;
register int table_size;
register int ns, ne;
register wchar_t cs, ce;
{
register int i;
register int tns, tne;
register wchar_t tcs, tce;
register ccl_chars_t *table;
register ccl_chars_t *saved_table;
int saved_i;
dprintf("Inserting {%o, %o} to table %o\n", cs, ce, table_base);
/*
* Searching the table to find out where should put the new item.
*/
for (i = 0, table = table_base; i < table_size; i++, table++) {
tns = table->cc_ns;
tcs = table->cc_cs;
tne = table->cc_ne;
tce = table->cc_ce;
if (MLCMPLT(ne, ce, tns, (tcs - 1))) {
/*
* Quick! insert to font of current table entries.
*/
qinsert:
table_size++;
for (; i < table_size; i++, table++) {
tns = table->cc_ns;
tcs = table->cc_cs;
tne = table->cc_ne;
tce = table->cc_ce;
table->cc_ns = ns;
table->cc_cs = cs;
table->cc_ne = ne;
table->cc_ce = ce;
ns = tns;
cs = tcs;
ne = tne;
ce = tce;
}
goto add_null;
} else if (MLCMPLE(tns, (tcs - 1), ns, cs) &&
MLCMPLE(ns, cs, tne, (tce + 1))) {
/*
* Starting point is within the current entry.
*/
if (MLCMPGT(tns, tcs, ns, cs)) {
table->cc_ns = ns;
table->cc_cs = cs;
}
if (MLCMPLE(ne, ce, tne, tce)) {
return (table_size);
}
goto combine;
}
}
/*
* Adding new one to end of table.
*/
table->cc_ns = ns;
table->cc_cs = cs;
table->cc_ne = ne;
table->cc_ce = ce;
table_size++;
goto add_null;
combine:
/*
* Check and try to combine the new entry with rest of entries.
*/
if ((i + 1) >= table_size) {
table->cc_ne = ne;
table->cc_ce = ce;
return (table_size);
}
saved_table = table++;
saved_i = i++;
/*
* Finding the spot where we should put the end point.
*/
for (; i < table_size; i++, table++) {
if (MLCMPLT(ne, ce, table->cc_ns, (table->cc_cs - 1))) {
break;
} else
if (MLCMPLE(table->cc_ns, (table->cc_cs - 1), ne, ce) &&
MLCMPLE(ne, ce, table->cc_ne, (table->cc_ce + 1))) {
/*
* Tack with this table.
*/
if (MLCMPLT(ne, ce, table->cc_ne, table->cc_ce)) {
ne = table->cc_ne;
ce = table->cc_ce;
}
table++;
i++;
break;
}
}
saved_table->cc_ne = ne;
saved_table->cc_ce = ce;
saved_i = table_size - (i - saved_i - 1);
/*
* Moving the rest of entries.
*/
for (; i < table_size; i++, table++)
*(++saved_table) = *table;
table_size = saved_i;
add_null:
table_base[table_size].cc_cs = (wchar_t)0x0;
table_base[table_size].cc_ce = (wchar_t)0x0;
return (table_size);
}
static int
delete_table(table_base, table_size, ns, cs, ne, ce)
ccl_chars_t *table_base;
register int table_size;
register int ns, ne;
register wchar_t cs, ce;
{
register int i;
int saved_i;
register ccl_chars_t *table;
register ccl_chars_t *saved_table;
register int tns;
register wchar_t tcs;
register int tne;
register wchar_t tce;
for (i = 0, table = table_base; i < table_size; i++, table++) {
tns = table->cc_ns;
tcs = table->cc_cs;
tne = table->cc_ne;
tce = table->cc_ce;
if (MLCMPLT(ne, ce, tns, tcs))
return (table_size);
else if (MLCMPLT(ne, ce, tne, tce)) {
if (MLCMPLE(ns, cs, tns, tcs)) {
/*
* Shrink type 1.
*/
table->cc_ns = ne;
table->cc_cs = ce + 1;
return (table_size);
} else {
/*
* Spliting !!
*/
table->cc_ns = ne;
table->cc_cs = ce + 1;
tne = ns;
tce = cs - 1;
table_size++;
for (; i < table_size; i++, table++) {
ns = table->cc_ns;
cs = table->cc_cs;
ne = table->cc_ne;
ce = table->cc_ce;
table->cc_ns = tns;
table->cc_cs = tcs;
table->cc_ne = tne;
table->cc_ce = tce;
tns = ns;
tcs = cs;
tne = ne;
tce = ce;
}
return (table_size);
}
} else if (MLCMPLE(ns, cs, tne, tce)) {
if (MLCMPGT(ns, cs, tns, tcs)) {
/*
* Shrink current table(type 2).
*/
table->cc_ne = ns;
table->cc_ce = cs - 1;
table++;
i++;
}
/*
* Search for the end point.
*/
saved_i = i;
saved_table = table;
for (; i < table_size; i++, table++) {
if (MLCMPLT(ne, ce,
table->cc_ns, table->cc_cs)) {
/*
* Easy point, no shrinks!
*/
break;
} else if (MLCMPGT(table->cc_ne, table->cc_ce,
ne, ce)) {
/*
* Shrinking...
*/
table->cc_ns = ne;
table->cc_cs = ce + 1;
break;
}
}
/*
* Moving(removing) backword.
*/
saved_i = table_size - (i - saved_i);
for (; i < table_size; i++)
*saved_table++ = *table++;
return (saved_i);
}
}
return (table_size);
}
#ifdef DEBUG
dump_table(table, size)
register ccl_chars_t *table;
register int size;
{
register int i;
if (! dbg)
return;
printf("Duming table %o with size %d\n", table, size);
size++; /* To watch out NULL */
for (i = 0; i < size; i++, table++)
{
printf("{%3o, %3o}, ", table->cc_cs, table->cc_ce);
}
printf("\n");
}
#endif /* DEBUG */
match(pfa, p)
register struct fa *pfa;
register wchar_t *p;
{
register count;
register int n, ns, ne;
register wchar_t c, cs, ce;
if (p == 0)
return (0);
if (pfa->cc.h == 1) { /* fast test for first character, if possible */
ns = (++pfa)->cc.s.cc_ns;
cs = (pfa)->cc.s.cc_cs;
ne = (pfa)->cc.s.cc_ne;
ce = (pfa)->cc.s.cc_ce;
do {
c = *p;
n = wcsetno(c);
if (MLCMPLE(ns, cs, n, c) &&
MLCMPLE(n, c, ne, ce)) {
p++;
pfa = pfa->st;
goto adv;
}
} while (*p++ != 0);
return (0);
}
adv: if ((count = pfa->cc.h) < 0)
return (1);
do {
c = *p;
n = wcsetno(c);
for (pfa += count; count; count--, pfa--) {
ns = (pfa)->cc.s.cc_ns;
cs = (pfa)->cc.s.cc_cs;
ne = (pfa)->cc.s.cc_ne;
ce = (pfa)->cc.s.cc_ce;
if (MLCMPLE(ns, cs, n, c) && MLCMPLE(n, c, ne, ce))
break;
}
pfa = pfa->st;
if ((count = pfa->cc.h) < 0)
return (1);
} while (*p++ != 0);
return (0);
}