Annotation of coherent/b/bin/troff/hyphen.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * hyphen.c
                      3:  * Nroff/Troff.
                      4:  * Hyphenation.
                      5:  */
                      6: 
                      7: #include <ctype.h>
                      8: #include "roff.h"
                      9: 
                     10: /*
                     11:  * Try to hyphenate the word found in the word buffer.
                     12:  */
                     13: hyphen(cp1, cp2)
                     14: CODE *cp1;
                     15: CODE *cp2;
                     16: {
                     17:        register CODE *cpl;
                     18:        register int n;
                     19:        int wi1, wi2, len;
                     20: 
                     21:        cpl = cp1;
                     22:        n = cp2 - cp1;
                     23:        while (n--)
                     24:                hyphbuf[n] = 0;
                     25:        while (cp1 < cp2) {
                     26:                n = cp2[-1].c_arg.c_code;
                     27:                if (isascii(n) && isalpha(n))
                     28:                        break;
                     29:                --cp2;
                     30:        }
                     31:        len = cp2 - cp1;
                     32:        while (cp1 < cp2) {
                     33:                n = cp1->c_arg.c_code;
                     34:                if (isascii(n) && isalpha(n))
                     35:                        break;
                     36:                cp1++;
                     37:        }
                     38:        if (len <= 4)
                     39:                return;
                     40:        wi1 = 0;
                     41:        wi2 = len;
                     42:        if (except(cpl, hyphbuf, wi1, wi2))
                     43:                return;
                     44:        wi2 = 1 + suffix(cpl, hyphbuf, wi2-1, wi1-1);
                     45:        wi1 = prefix(cpl, hyphbuf, wi1, wi2);
                     46:        middle(cpl, hyphbuf, wi1, wi2);
                     47:        n = len;
                     48:        hyphbuf[0] = 0;
                     49:        hyphbuf[n-3] = 0;
                     50:        hyphbuf[n-2] = 0;
                     51:        hyphbuf[n-1] = 0;
                     52:        if (wi2-wi1 <= 2) {
                     53:                hyphbuf[wi1] = 0;
                     54:                hyphbuf[wi2-1] = 0;
                     55:        }
                     56:        n = wi2;
                     57:        if (--n>=0 && cpl[n].c_arg.c_code==LEEE) {
                     58:                int m;
                     59:                m = 3;
                     60:                while (n && m--)
                     61:                        hyphbuf[n--] = 0;
                     62:        }
                     63:        n = wi2;
                     64:        if (n>=2 && cpl[--n].c_arg.c_code==LDDD &&
                     65:            cpl[--n].c_arg.c_code==LEEE) {
                     66:                if (--n<1 || cpl[n].c_arg.c_code!=LZZZ ||
                     67:                    cpl[n-1].c_arg.c_code!=LIII) {
                     68:                        if (--n >= 0)
                     69:                                hyphbuf[n] = 0;
                     70:                        if (--n >= 0)
                     71:                                hyphbuf[n] = 0;
                     72:                }
                     73:        }
                     74: }
                     75: 
                     76: /*
                     77:  * Look for exception words.
                     78:  */
                     79: except(wbuf, hbuf, wi1, wi2)
                     80: CODE *wbuf;
                     81: char *hbuf;
                     82: {
                     83:        unsigned ti, ti0, ti1, ti2, wih, c1, c2;
                     84:        register int wi, n;
                     85:        register char *bp;
                     86: 
                     87:        ti = ti1 = 0;   /* ti = 0 by c.e.f triggered by lint error */
                     88:        ti2 = EXCSIZE;
                     89:        for (;;) {
                     90:                ti0 = ti;
                     91:                if ((ti=(ti1+ti2)/2) == ti0)
                     92:                        goto fail;
                     93:                wi = wi1;
                     94:                wih = wi1;
                     95:                bp = exctab[ti];
                     96:                for (;;) {
                     97:                        if (*bp == LEOK) {
                     98:                                if (wi == wi2)
                     99:                                        return 1;
                    100:                                if (wi==wi2-1 && wbuf[wi].c_arg.c_code==LSSS)
                    101:                                        return 1;
                    102:                                ti1 = ti;
                    103:                                break;
                    104:                        }
                    105:                        if (*bp == LHYP) {
                    106:                                bp++;
                    107:                                wih = wi;
                    108:                                hbuf[wi-1] = 1;
                    109:                                continue;
                    110:                        }
                    111:                        if (wi >= wi2) {
                    112:                                ti1 = ti;
                    113:                                break;
                    114:                        }
                    115:                        if ((c1=wbuf[wi++].c_arg.c_code) != (c2 = *bp++)) {
                    116:                                if (c1 > c2)
                    117:                                        ti1 = ti;
                    118:                                else
                    119:                                        ti2 = ti;
                    120:                                break;
                    121:                        }
                    122:                }
                    123:                for (wi=wi1; wi<wih; wi++)
                    124:                        hbuf[wi] = 0;
                    125:        }
                    126: fail:
                    127:        for (n=wi1; n<wi2; n++)
                    128:                hbuf[n] = 0;
                    129:        return 0;
                    130: }
                    131: 
                    132: /*
                    133:  * Look for prefixes.
                    134:  */
                    135: prefix(wbuf, hbuf, wi1, wi2)
                    136: CODE *wbuf;
                    137: char *hbuf;
                    138: register int wi2;
                    139: {
                    140:        unsigned ti, ti0, ti1, ti2, c1, c2, con;
                    141:        register int wi, wih;
                    142:        register char *bp;
                    143: 
                    144:        do {
                    145:                ti0 = -1;
                    146:                ti = ti1 = 0;   /* ti = 0 by c.e.f triggered by lint */
                    147:                ti2 = PRESIZE;
                    148:                for (;;) {
                    149:                        ti0 = ti;
                    150:                        if ((ti=(ti1+ti2)/2) == ti0)
                    151:                                return wi1;
                    152:                        wi = wi1;
                    153:                        wih = wi1;
                    154:                        bp = pretab[ti];
                    155:                        for (;;) {
                    156:                                if (*bp == LEOK) {
                    157:                                        bp++;
                    158:                                        goto patn;
                    159:                                }
                    160:                                if (*bp == LHYP) {
                    161:                                        bp++;
                    162:                                        wih = wi;
                    163:                                        hbuf[wi-1] = 1;
                    164:                                        continue;
                    165:                                }
                    166:                                if (wi >= wi2)
                    167:                                        return wi1;
                    168:                                if ((c1=wbuf[wi++].c_arg.c_code) !=
                    169:                                    (c2 = *bp++)) {
                    170:                                        if (c1 > c2)
                    171:                                                ti1 = ti;
                    172:                                        else
                    173:                                                ti2 = ti;
                    174:                                        break;
                    175:                                }
                    176:                        }
                    177:                        for (wi=wi1; wi<wih; wi++)
                    178:                                hyphbuf[wi] = 0;
                    179:                }
                    180:        patn:
                    181:                if (automate(bp, &wi1, &con, 1, wbuf, hbuf, wi, wi2) == 0) {
                    182:                        while (wi > wi1)
                    183:                                hbuf[--wi] = 0;
                    184:                        return wi1;
                    185:                }
                    186:        } while (con != 0);
                    187:        return wi1;
                    188: }
                    189: 
                    190: /*
                    191:  * Look for suffixes.
                    192:  */
                    193: suffix(wbuf, hbuf, wi1, wi2)
                    194: CODE *wbuf;
                    195: char *hbuf;
                    196: register int wi2;
                    197: {
                    198:        unsigned ti, ti0, ti1, ti2, c1, c2, con;
                    199:        register int wi, wih;
                    200:        register char *bp;
                    201: 
                    202:        do {
                    203:                ti0 = -1;
                    204:                ti = ti1 = 0;   /* ti = 0 by cef triggered by lint */
                    205:                ti2 = SUFSIZE;
                    206:                for (;;) {
                    207:                        ti0 = ti;
                    208:                        if ((ti=(ti1+ti2)/2) == ti0)
                    209:                                return wi1;
                    210:                        wi = wi1;
                    211:                        wih = wi1;
                    212:                        bp = suftab[ti];
                    213:                        for (;;) {
                    214:                                if (*bp == LEOK) {
                    215:                                        bp++;
                    216:                                        goto patn;
                    217:                                }
                    218:                                if (*bp == LHYP) {
                    219:                                        bp++;
                    220:                                        wih = wi;
                    221:                                        hbuf[wi] = 1;
                    222:                                        continue;
                    223:                                }
                    224:                                if (wi <= wi2)
                    225:                                        return wi1;
                    226:                                if ((c1=wbuf[wi--].c_arg.c_code) !=
                    227:                                    (c2 = *bp++)) {
                    228:                                        if (c1 > c2)
                    229:                                                ti1 = ti;
                    230:                                        else
                    231:                                                ti2 = ti;
                    232:                                        break;
                    233:                                }
                    234:                        }
                    235:                        for (wi=wi1; wi>wih; wi--)
                    236:                                hyphbuf[wi] = 0;
                    237:                }
                    238:        patn:
                    239:                if (automate(bp, &wi1, &con, -1, wbuf, hbuf, wi, wi2) == 0) {
                    240:                        while (wi < wi1)
                    241:                                hbuf[++wi] = 0;
                    242:                        return wi1;
                    243:                }
                    244:        } while (con != 0);
                    245:        return wi1;
                    246: }
                    247: 
                    248: /*
                    249:  * Try to hyphenate the middle of a word.
                    250:  */
                    251: middle(wbuf, hbuf, wi1, wi2)
                    252: CODE *wbuf;
                    253: char *hbuf;
                    254: {
                    255:        int new, bil, c2, c3, n;
                    256:        unsigned con;
                    257:        register int wi, bi, c1;
                    258: 
                    259:        wi = wi1;
                    260:        bi = 0;
                    261:        while (wi < wi2) {
                    262:                c1 = wbuf[wi++].c_arg.c_code;
                    263:                if (wi<wi2 && wbuf[wi].c_arg.c_code==LHHH) {
                    264:                        wi++;
                    265:                        switch (c1) {
                    266:                        case LCCC:
                    267:                                c1 = LDCH;
                    268:                                break;
                    269:                        case LGGG:
                    270:                                c1 = LDGH;
                    271:                                break;
                    272:                        case LPPP:
                    273:                                c1 = LDPH;
                    274:                                break;
                    275:                        case LSSS:
                    276:                                c1 = LDSH;
                    277:                                break;
                    278:                        case LTTT:
                    279:                                c1 = LDTH;
                    280:                                break;
                    281:                        default:
                    282:                                --wi;
                    283:                                break;
                    284:                        }
                    285:                }
                    286:                hletbuf[bi] = c1;
                    287:                hindbuf[bi++] = wi-1;
                    288:        }
                    289:        bil = bi-2;
                    290:        for (bi=0; bi<bil; bi++) {
                    291:                if (!vowel(hletbuf[bi]))
                    292:                        continue;
                    293:                c1 = hletbuf[bi+1];
                    294:                c2 = hletbuf[bi+2];
                    295:                if (c1==c2 && consn(c1)) {
                    296:                        if (c1 == LLLL)
                    297:                                continue;
                    298:                        if (c1 == LSSS) {
                    299:                                if (bi>=bil-1 || !vowel(hletbuf[bi+3]))
                    300:                                        continue;
                    301:                                if (automate(mm0code, &new, &con, 1,
                    302:                                        wbuf, hbuf, hindbuf[bi+3], wi2)==0)
                    303:                                        continue;
                    304:                        }
                    305:                        hbuf[hindbuf[++bi]] = 1;
                    306:                        continue;
                    307:                }
                    308:                if (c1==LCCC && c2==LKKK) {
                    309:                        hbuf[hindbuf[bi+=2]] = 1;
                    310:                        continue;
                    311:                }
                    312:                if (c1==LQQQ && c2==LUUU) {
                    313:                        hbuf[hindbuf[bi]] = 1;
                    314:                        continue;
                    315:                }
                    316:                if (bi < bil-1) {
                    317:                        c3 = hletbuf[bi+3];
                    318:                        if (!consn(c1) || !consn(c2) || !vowel(c3))
                    319:                                continue;
                    320:                        if ((n=matpair(c1, c2)) == 2)
                    321:                                continue;
                    322:                        if (n==1 && automate(mm1code, &new, &con, 1,
                    323:                                wbuf, hbuf, hindbuf[bi+3], wi2)==0)
                    324:                                continue;
                    325:                        hbuf[hindbuf[++bi]] = 1;
                    326:                        continue;
                    327:                }
                    328:        }
                    329: }
                    330: 
                    331: /*
                    332:  * See if we match a set of double consonants.  If we do,
                    333:  * return the associated number in the table.
                    334:  */
                    335: matpair(c1, c2)
                    336: register int c1;
                    337: {
                    338:        register int c;
                    339:        register char *cp;
                    340: 
                    341:        cp = dbctab;
                    342:        while ((c = *cp++) != LNUL) {
                    343:                if (c1 < c)
                    344:                        return 0;
                    345:                if (c1 > c) {
                    346:                        cp += 2;
                    347:                        continue;
                    348:                }
                    349:                if (c2 != *cp++) {
                    350:                        cp++;
                    351:                        continue;
                    352:                }
                    353:                return *cp;
                    354:        }
                    355:        return 0;
                    356: }
                    357: 
                    358: /*
                    359:  * Given a pattern string, execute it on the given word buffer.
                    360:  */
                    361: automate(patp, newp, conp, dirn, wbuf, hbuf, wi1, wi2)
                    362: char *patp;
                    363: int *newp;
                    364: unsigned *conp;
                    365: CODE *wbuf;
                    366: char *hbuf;
                    367: {
                    368:        int wi, wis;
                    369:        register int c, n;
                    370:        register char *bp;
                    371: 
                    372:        bp = patp;
                    373:        *conp = 0;
                    374:        wi = wi1;
                    375:        wis = wi1;
                    376:        for (;;) {
                    377:                switch (*bp++) {
                    378:                case LNUL:
                    379:                        goto succ;
                    380:                case LHYP:
                    381:                        wis = wi;
                    382:                        *conp = 0;
                    383:                        hbuf[wi-(dirn>0?1:0)] = 1;
                    384:                        continue;
                    385:                case LRHP:
                    386:                        hbuf[wi-(dirn>0?1:0)] = 0;
                    387:                        continue;
                    388:                case LCON:
                    389:                        *conp = 1;
                    390:                        continue;
                    391:                case LNEW:
                    392:                        n = *bp++;
                    393:                        if (wi != wi2) {
                    394:                                c = wbuf[wi].c_arg.c_code;
                    395:                                wi += dirn;
                    396:                                continue;
                    397:                        }
                    398:                        if (n == 1)
                    399:                                goto fail;
                    400:                        if (n == 2)
                    401:                                goto succ;
                    402:                        bp += n-3;
                    403:                        continue;
                    404:                case LOLD:
                    405:                        wi -= dirn;
                    406:                        c = wbuf[wi-dirn].c_arg.c_code;
                    407:                        continue;
                    408:                case LBRF:
                    409:                        goto fail;
                    410:                case LBRS:
                    411:                        goto succ;
                    412:                case LCBT:
                    413:                        if (*bp++ != c) {
                    414:                                bp++;
                    415:                                continue;
                    416:                        }
                    417:                        if ((n = *bp++) == 1)
                    418:                                goto fail;
                    419:                        if (n == 2)
                    420:                                goto succ;
                    421:                        bp += n-3;
                    422:                        continue;
                    423:                case LCBF:
                    424:                        if (*bp++ == c) {
                    425:                                bp++;
                    426:                                continue;
                    427:                        }
                    428:                        if ((n = *bp++) == 1)
                    429:                                goto fail;
                    430:                        if (n == 2)
                    431:                                goto succ;
                    432:                        bp += n-3;
                    433:                        continue;
                    434:                default:
                    435:                        panic("bad pattern");
                    436:                }
                    437:        }
                    438: succ:
                    439:        *newp = wis;
                    440:        return 1;
                    441: fail:
                    442:        return 0;
                    443: }
                    444: 
                    445: /*
                    446:  * See if the given code is a vowel.
                    447:  */
                    448: vowel(c)
                    449: register int c;
                    450: {
                    451:        if (c>=LAAA && c<=LYYY && contab[c-LAAA]==0)
                    452:                return 1;
                    453:        return 0;
                    454: }
                    455: 
                    456: /*
                    457:  * See if the given code is a consonant.
                    458:  */
                    459: consn(c)
                    460: register int c;
                    461: {
                    462:        if (c>=LAAA && c<=LDTH && contab[c-LAAA]==1)
                    463:                return 1;
                    464:        return 0;
                    465: }
                    466: 
                    467: /*
                    468:  * Code to fail if we match ((er|ers)$).
                    469:  */
                    470: char mm0code[] ={
                    471:         0005, 0002, 0012, 0051, 0002, 0005, 0002, 0012,
                    472:         0066, 0002, 0005, 0001, 0012, 0067, 0002, 0005,
                    473:         0001, 0010, 0000
                    474: };
                    475: 
                    476: /*
                    477:  * Code to fail if we match ((er|ers|age|ages|est)$).
                    478:  */
                    479: char mm1code[] ={
                    480:         0005, 0002, 0011, 0051, 0030, 0012, 0045, 0002,
                    481:         0005, 0002, 0012, 0053, 0002, 0005, 0002, 0012,
                    482:         0051, 0002, 0005, 0001, 0012, 0067, 0002, 0005,
                    483:         0001, 0010, 0005, 0002, 0011, 0066, 0016, 0012,
                    484:         0067, 0002, 0005, 0002, 0012, 0070, 0002, 0005,
                    485:         0001, 0010, 0005, 0001, 0012, 0067, 0002, 0005,
                    486:         0001, 0010, 0000
                    487: };
                    488: 
                    489: /*
                    490:  * Table to determine whether a letter is a constant or a vowel.
                    491:  */
                    492: char contab[] ={
                    493:        0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
                    494:        1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
                    495: };
                    496: 
                    497: /*
                    498:  * Pairs of consonants which aren't allowed somewhere.
                    499:  */
                    500: char dbctab[] ={
                    501:        LBBB, LLLL, 2,
                    502:        LBBB, LRRR, 2,
                    503:        LCCC, LLLL, 2,
                    504:        LCCC, LRRR, 2,
                    505:        LFFF, LLLL, 2,
                    506:        LFFF, LRRR, 2,
                    507:        LFFF, LTTT, 1,
                    508:        LGGG, LLLL, 2,
                    509:        LGGG, LRRR, 2,
                    510:        LKKK, LNNN, 2,
                    511:        LLLL, LDDD, 1,
                    512:        LLLL, LKKK, 2,
                    513:        LLLL, LQQQ, 2,
                    514:        LMMM, LPPP, 1,
                    515:        LNNN, LDDD, 1,
                    516:        LNNN, LGGG, 1,
                    517:        LNNN, LKKK, 2,
                    518:        LNNN, LSSS, 1,
                    519:        LNNN, LTTT, 1,
                    520:        LNNN, LXXX, 2,
                    521:        LNNN, LDCH, 2,
                    522:        LPPP, LLLL, 2,
                    523:        LPPP, LRRR, 2,
                    524:        LRRR, LGGG, 1,
                    525:        LRRR, LKKK, 2,
                    526:        LRRR, LMMM, 1,
                    527:        LRRR, LNNN, 1,
                    528:        LRRR, LTTT, 1,
                    529:        LSSS, LPPP, 2,
                    530:        LSSS, LQQQ, 2,
                    531:        LSSS, LTTT, 1,
                    532:        LTTT, LRRR, 2,
                    533:        LTTT, LDCH, 2,
                    534:        LWWW, LHHH, 2,
                    535:        LWWW, LLLL, 2,
                    536:        LWWW, LNNN, 2,
                    537:        LWWW, LRRR, 2,
                    538:        LDCH, LLLL, 2,
                    539:        LDCH, LRRR, 2,
                    540:        LDDD, LGGG, 2,
                    541:        LDDD, LRRR, 2,
                    542:        LDGH, LTTT, 2,
                    543:        LDPH, LRRR, 2,
                    544:        LDTH, LRRR, 2,
                    545:        LNUL
                    546: };
                    547: 
                    548: /* end of hyphen.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.