static Rune latin_fold_tab[] =
{
/* Table to fold latin 1 characters to ASCII equivalents
based at Rune value 0xc0
À Á Â Ã Ä Å Æ Ç
È É Ê Ë Ì Í Î Ï
Ð Ñ Ò Ó Ô Õ Ö ×
Ø Ù Ú Û Ü Ý Þ ß
à á â ã ä å æ ç
è é ê ë ì í î ï
ð ñ ò ó ô õ ö ÷
ø ù ú û ü ý þ ÿ
*/
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
'o', 'u', 'u', 'u', 'u', 'y', 0 , 0 ,
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
'o', 'u', 'u', 'u', 'u', 'y', 0 , 'y',
};
static Rune *ttabstack[20];
static int ntt;
/*
* tab is an array of n Assoc's, sorted by key.
* Look for key in tab, and return corresponding val
* or -1 if not there
*/
long
lookassoc(Assoc *tab, int n, char *key)
{
Assoc *q;
long i, low, high;
int r;
for(low = -1, high = n; high > low+1; ){
i = (high+low)/2;
q = &tab[i];
if((r=strcmp(key, q->key))<0)
high = i;
else if(r == 0)
return q->val;
else
low=i;
}
return -1;
}
long
looknassoc(Nassoc *tab, int n, long key)
{
Nassoc *q;
long i, low, high;
for(low = -1, high = n; high > low+1; ){
i = (high+low)/2;
q = &tab[i];
if(key < q->key)
high = i;
else if(key == q->key)
return q->val;
else
low=i;
}
return -1;
}
/*
* Write the rune r to bout, keeping track of line length
* and breaking the lines (at blanks) when they get too long
*/
void
outrune(long r)
{
if(outinhibit)
return;
if(++linelen > breaklen && r == L' ') {
Bputc(bout, '\n');
linelen = 0;
} else
Bputrune(bout, r);
}
void
outrunes(Rune *rp)
{
Rune r;
while((r = *rp++) != 0)
outrune(r);
}
/* like outrune, but when arg is know to be a char */
void
outchar(int c)
{
if(outinhibit)
return;
if(++linelen > breaklen && c == ' ') {
c ='\n';
linelen = 0;
}
Bputc(bout, c);
}
/*
* Go to new line if not already there; indent if ind != 0.
* If ind > 1, leave a blank line too.
* Slight hack: assume if current line is only one or two
* characters long, then they were spaces.
*/
void
outnl(int ind)
{
if(outinhibit)
return;
if(ind) {
if(ind > 1) {
if(linelen > 2)
Bputc(bout, '\n');
Bprint(bout, "\n ");
} else if(linelen == 0)
Bprint(bout, " ");
else if(linelen == 1)
Bputc(bout, ' ');
else if(linelen != 2)
Bprint(bout, "\n ");
linelen = 2;
} else {
if(linelen) {
Bputc(bout, '\n');
linelen = 0;
}
}
}
/*
* Fold the runes in null-terminated rp.
* Use the sort(1) definition of folding (uppercase to lowercase,
* latin1-accented characters to corresponding unaccented chars)
*/
void
fold(Rune *rp)
{
Rune r;
while((r = *rp) != 0) {
if (rislatin1(r) && latin_fold_tab[r-0xc0])
r = latin_fold_tab[r-0xc0];
if(risupper(r))
r = rtolower(r);
*rp++ = r;
}
}
/*
* Like fold, but put folded result into new
* (assumed to have enough space).
* old is a regular expression, but we know that
* metacharacters aren't affected
*/
void
foldre(char *new, char *old)
{
Rune r;
while(*old) {
old += chartorune(&r, old);
if (rislatin1(r) && latin_fold_tab[r-0xc0])
r = latin_fold_tab[r-0xc0];
if(risupper(r))
r = rtolower(r);
new += runetochar(new, &r);
}
*new = 0;
}
/*
* acomp(s, t) returns:
* -2 if s strictly precedes t
* -1 if s is a prefix of t
* 0 if s is the same as t
* 1 if t is a prefix of s
* 2 if t strictly precedes s
*/
/*
* Conversion of unsigned number to long, no overflow detection
*/
long
runetol(Rune *r)
{
int c;
long n;
n = 0;
for(;; r++){
c = *r;
if(L'0'<=c && c<=L'9')
c -= '0';
else
break;
n = n*10 + c;
}
return n;
}
/*
* See if there is a rune corresponding to the accented
* version of r with accent acc (acc in [LIGS..LIGE-1]),
* and return it if so, else return NONE.
*/
Rune
liglookup(Rune acc, Rune r)
{
Rune *p;
/*
* Maintain a translation table stack (a translation table
* is an array of Runes indexed by bytes or 7-bit bytes).
* If starting is true, push the curtab onto the stack
* and return newtab; else pop the top of the stack and
* return it.
* If curtab is 0, initialize the stack and return.
*/
Rune *
changett(Rune *curtab, Rune *newtab, int starting)
{
if(curtab == 0) {
ntt = 0;
return 0;
}
if(starting) {
if(ntt >= asize(ttabstack)) {
if(debug)
err("translation stack overflow");
return curtab;
}
ttabstack[ntt++] = curtab;
return newtab;
} else {
if(ntt == 0) {
if(debug)
err("translation stack underflow");
return curtab;
}
return ttabstack[--ntt];
}
}