Annotation of 43BSD/contrib/B/src/bed/getc.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
                      2: 
                      3: /* $Header: getc.c,v 2.5 85/08/22 16:02:44 timo Exp $ */
                      4: 
                      5: /* B editor -- read key definitions from file */
                      6: 
                      7: #include "b.h"
                      8: #include "feat.h"
                      9: #ifdef LINDA
                     10: #include "b1mem.h"
                     11: #define syserr EDsyserr
                     12: #else !LINDA
                     13: #define freemem(p) free(p)
                     14: #endif !LINDA
                     15: #include "file.h"
                     16: #include "keys.h"
                     17: 
                     18: #include <ctype.h>
                     19: 
                     20: extern bool dflag;
                     21: 
                     22: #define ESC '\033'
                     23: 
                     24: /*
                     25: This file contains a little parser for key definition files.
                     26: To allow sufficient freedom in preparing such a file, a simple
                     27: grammar has been defined according to which the file is parsed.
                     28: The parsing process is extremely simple, as it can be done
                     29: top-down using recursive descent.
                     30: 
                     31: 
                     32: Lexical conventions:
                     33: 
                     34: - Blanks between lexical symbols are gnored.
                     35: - From '#' to end of line is comment (except inside strings).
                     36: - Strings are delimited by single or double quotes and
                     37:   use the same escape sequences as C strings, plus:
                     38:   \e or \E means an ESCape ('\033').
                     39: - Command names are like C identifiers ([a-zA-Z_][a-zA-Z0-9_]*).
                     40:   Upper/lower case distinction is significant.
                     41: - numbers are octal or decimal integers in C-style (leading zero means octal)
                     42: - After '^' a character is expected, this must be a letter or one of @^_[]\ .
                     43: 
                     44: Syntax in modified BNF ([] mean 0 or 1, * means 0 or more, + means 1 or more):
                     45: 
                     46:    file: line*
                     47:    line: [def] [comment]
                     48:    def: commandname '=' rhs
                     49:    rhs: item+
                     50:    item: string | '^' character | number
                     51: 
                     52: 
                     53: Notes:
                     54: 
                     55: - A definition for command "term_init" defines a string to be sent
                     56:   TO the terminal at initialization time, e.g. to set programmable
                     57:   function key definitions.  Similar for "term_done" on exiting.
                     58: - Command names are  conventional editor commands.
                     59: 
                     60: */
                     61: 
                     62: 
                     63: #ifndef LINDA
                     64: /* Defines subroutine that used to be in the support levels: */
                     65: 
                     66: Hidden string getmem(nbytes)
                     67:        unsigned nbytes;
                     68: {
                     69:        string malloc();
                     70:        string pointer= malloc(nbytes);
                     71: 
                     72:        if (pointer == NULL)
                     73:                syserr("memory full in initkeys");
                     74:        return pointer;
                     75: }
                     76: 
                     77: Hidden string regetmem(pp, nbytes)
                     78:        string *pp;
                     79:        unsigned nbytes;
                     80: {
                     81:        *pp= realloc(*pp, nbytes);
                     82:        if (*pp == NULL)
                     83:                syserr("memory full in initkeys (regetmem)");
                     84: }
                     85: #endif !LINDA
                     86: 
                     87: 
                     88: #define COMMENT '#' /* Not B-like but very UNIX-like */
                     89: #define MAXDEFS 100
                     90: 
                     91: Hidden FILE *fp; /* File from which to read */
                     92: Hidden string filename; /* File name for error messages */
                     93: Hidden char nextc; /* Next character to be analyzed */
                     94: Hidden bool eof; /* EOF seen? */
                     95: Hidden int lcount; /* Current line number */
                     96: Hidden bool errcount; /* Number of errors detected */
                     97: 
                     98: 
                     99: struct tabent {
                    100:        int code;
                    101:        string name;
                    102:        string def;
                    103: };
                    104: 
                    105: /* Table of key definitions, mostly filled by reading definitions from a file.
                    106:    The "I" macro has two arguments: the default for termcap and that for
                    107:    the IBM PC.  It expands to either depending on whether IBMPC is defined.
                    108:    'def' fields initialized with a string starting with '=' are termcap names,
                    109:    and are replaced by the corresponding termcap entry (NULL if none).
                    110:    On the IBM PC, 'extended codes' are by convention a null character
                    111:    followed by another character (usually the scan code).  Since the null
                    112:    character is rather unsuitable for use in C strings, we use \377 (hex FF)
                    113:    instead, a code which has no assigned graphic is the extended IBM PC
                    114:    character set.  E.g., F1 is 0-59, which we encode as \377\073 (since
                    115:    \073 is octal for 59 decimal).  For the exact codes, see for instance the
                    116:    BASIC 2.0 manual, appendix G, or the XT Technical Reference, page 2-14.
                    117: */
                    118: 
                    119: #ifdef IBMPC
                    120: #define I(tc, ibm) ibm
                    121: #else !IBMPC
                    122: #define I(tc, ibm) tc
                    123: #endif !IBMPC
                    124: 
                    125: Visible struct tabent deftab[MAXDEFS] = {
                    126:        /* General rule:
                    127:           unix => ctrl-x
                    128:           IBM  => alt-x
                    129:           where x is first letter of command name
                    130:        */
                    131:        {0377, "ignore", NULL}, /* Entry to ignore a key */
                    132:        {COPY, "copy", I(NULL, "\377\056")},
                    133:        {DELETE, "delete", I(NULL, "\377\040")},
                    134:        {DELETE, "delete", I(NULL, "\377\123")}, /* IBM DEL key */
                    135:        {ACCEPT, "accept", I(NULL, "\377\022")}, /* ^E, alt-E */
                    136:        {ACCEPT, "end", I(NULL, "\377\117")}, /* IBM END key */
                    137:        {'\t', "tab", NULL}, /* = ACCEPT in Bed, insert tab in Linda */
                    138:        {UNDO, "undo"}, /* Always backspace = ^H */
                    139:        {REDRAW, "redraw", I(NULL, "\377\046")}, /* ^L, alt-L */
                    140:        {REDRAW, "look"},
                    141:        {RETURN, "newline"}, /* Always ^M */
                    142:        {REDO, "redo", I(NULL, "\177")}, /* IBM ctrl-BS = ASCII 177 (DEL) */
                    143:        {EXIT, "exit", I(NULL, "\377\055")}, /* ^X, alt-X */
                    144: 
                    145: #ifdef RECORDING
                    146:        /*
                    147:         * The IBM-PC has a problem here in ANSI.SYS mode: ctrl-P is
                    148:         * unusable because it means Print Screen, and alt-R is unusable
                    149:         * because it transmits 0, 19 but 19 is ctrl-S which means stop
                    150:         * output :-(.
                    151:         * The only reasonable place to put the things would then be on
                    152:         * function keys.  You should do this in the key definitions file. (?)
                    153:         */
                    154:        {PLAYBACK, "play", I(NULL, "\377\031")},
                    155:        {PLAYBACK, "playback", I(NULL, "\377\031")},
                    156:        {RECORD, "record", I(NULL, "\377\023")},
                    157: #endif RECORDING
                    158: 
                    159: #ifdef LINDA
                    160:        {BFIND, "bfind", I(NULL, "\377\060")},
                    161:        {FIND, "find", I(NULL, "\377\041")},
                    162:        {GLOBAL, "global", I(NULL, "\377\042")},
                    163:        {JOIN, "join", I(NULL, "\377\044")},
                    164:        {TOGGLE, "toggle", I(NULL, "\377\024")},
                    165:        {YANK, "yank", I(NULL, "\377\025")},
                    166:        {LITERAL, "literal", I(NULL, "\377\057")}, /* ^V, alt-V */
                    167: #endif LINDA
                    168: 
                    169:        {WIDEN, "widen", I("=k1", "\377\073")}, /* IBM F1 */
                    170:        {NARROW, "narrow", I("=k2", "\377\075")}, /* IBM F3 (!!!) */
                    171:        {NARROW, "first"},
                    172:        {RNARROW, "rnarrow", I("=k3", "\377\076")}, /* IBM F4 (!!!) */
                    173:        {RNARROW, "last"},
                    174:        {EXTEND, "extend", I("=k4", "\377\074")}, /* IBM F2 (!!!) */
                    175:        {UPARROW, "up", I("=ku", "\377\110")},
                    176:        {UPLINE, "upline", I("=k5", "\377\110")},
                    177:        {LEFTARROW, "left", I("=kl", "\377\113")},
                    178:        {PREVIOUS, "previous", I("=k6", NULL)},
                    179:        {RITEARROW, "right", I("=kr", "\377\115")},
                    180:        {NEXT, "next", I("=k7", NULL)},
                    181:        {DOWNARROW, "down", I("=kd", "\377\120")},
                    182:        {DOWNLINE, "downline", I("=k8", "\377\120")},
                    183: 
                    184:        {GOTO, "goto", I("\033g", NULL)}, /* Doesn't exist on IBM */
                    185: #ifdef HELPFUL
                    186:        {HELP, "help", I("\033?", "\377\104")}, /* ESC ?, IBM F10 */
                    187: #endif HELPFUL
                    188: 
                    189:        {0, "term_init", I("=ks", NULL)},
                    190:        {0, "term_done", I("=ke", NULL)},
                    191: };
                    192: 
                    193: #undef I
                    194: 
                    195: Hidden int ndefs;
                    196: 
                    197: 
                    198: Hidden Procedure err(fmt, arg)
                    199:        string fmt, arg;
                    200: {
                    201:        if (errcount == 0)
                    202:                fprintf(stderr, "Errors in key definitions file:\n");
                    203:        ++errcount;
                    204:        fprintf(stderr, "%s, line %d: ", filename, lcount);
                    205:        fprintf(stderr, fmt, arg);
                    206:        fprintf(stderr, "\n");
                    207: }
                    208: 
                    209: Hidden Procedure adv()
                    210: {
                    211:        int c;
                    212: 
                    213:        if (eof)
                    214:                return;
                    215:        c= getc(fp);
                    216:        if (c == EOF) {
                    217:                nextc= '\n';
                    218:                eof= Yes;
                    219:        }
                    220:        else {
                    221:                nextc= c;
                    222:                if (c == '\n')
                    223:                        ++lcount;
                    224:        }
                    225: }
                    226: 
                    227: Hidden Procedure skipsp()
                    228: {
                    229:        while (nextc == ' ' || nextc == '\t')
                    230:                adv();
                    231: }
                    232: 
                    233: Hidden int lookup(name)
                    234:        string name;
                    235: {
                    236:        int i;
                    237: 
                    238:        for (i= 0; i < ndefs; ++i) {
                    239:                if (deftab[i].name != NULL && strcmp(name, deftab[i].name) == 0)
                    240:                        return i;
                    241:        }
                    242:        return -1;
                    243: }
                    244: 
                    245: Hidden Procedure store(code, name, def)
                    246:        int code;
                    247:        string name;
                    248:        string def;
                    249: {
                    250:        struct tabent *d, *last= deftab+ndefs; 
                    251:        string p, q;
                    252: 
                    253:        /* Undefine conflicting definitions.  Conflicts arise
                    254:           when a command definition is an initial subsequence
                    255:           of another, or vice versa.  Key definitions (code < 0)
                    256:           are not undefined. */
                    257:        if (code > 0) {
                    258:                for (d= deftab; d < last; ++d) {
                    259:                        if (d->code >= 0 && d->def != NULL) {
                    260:                                for (p= def, q= d->def; *p == *q; ++p, ++q) {
                    261:                                        if (*p == '\0' || *q == '\0') {
                    262:                                                d->def= NULL;
                    263:                                                break;
                    264:                                        }
                    265:                                }
                    266:                        }
                    267:                }
                    268:        }
                    269: 
                    270:        /* Find a free slot with the same code and NULL definition */
                    271:        /* (For code == 0, the name must match instead of the code,
                    272:           and the definition need not be NULL) */
                    273:        for (d= deftab; d < last; ++d) {
                    274:                if (code == 0 ? strcmp(name, d->name) == 0
                    275:                        : (d->code == code && d->def == NULL))
                    276:                        break;
                    277:        }
                    278:        if (d == last) { /* Extend definition table */
                    279:                if (ndefs >= MAXDEFS) {
                    280:                        err("Too many key definitions", "");
                    281:                        return;
                    282:                }
                    283:                ++ndefs;
                    284:                d->code= code;
                    285:                d->name= name;
                    286:        }
                    287:        d->def= def;
                    288: }
                    289: 
                    290: Hidden string savestr(s)
                    291:        string s;
                    292: {
                    293:        string new;
                    294: 
                    295:        new= getmem((unsigned) (strlen(s) + 1));
                    296:        strcpy(new, s);
                    297:        return new;
                    298: }
                    299: 
                    300: Hidden Procedure append(to, item)
                    301:        string *to, item;
                    302: {
                    303:        int len= strlen(*to) + strlen(item) + 1;
                    304:        regetmem(to, len);
                    305:        strcat(*to, item);
                    306: }
                    307: 
                    308: Hidden string getname()
                    309: {
                    310:        char buffer[20];
                    311:        string bp;
                    312: 
                    313:        if (!isalpha(nextc) && nextc != '_') {
                    314:                err("No name where expected", "");
                    315:                return NULL;
                    316:        }
                    317:        for (bp= buffer; isalnum(nextc) || nextc == '_'; ) {
                    318:                if (bp < buffer + sizeof buffer - 1)
                    319:                        *bp++ = nextc;
                    320:                adv();
                    321:        }
                    322:        *bp= '\0';
                    323:        return savestr(buffer);
                    324: }
                    325: 
                    326: Hidden int getnumber()
                    327: {
                    328:        int base= (nextc == '0') ? 8 : 10;
                    329:        int i= 0;
                    330:        int d;
                    331: 
                    332:        for (;; adv()) {
                    333:                d= nextc-'0';
                    334:                if (d < 0 || d > 9)
                    335:                        break;
                    336:                if (d > base) {
                    337:                        err("8 or 9 in octal number", "");
                    338:                        return 0;
                    339:                }
                    340:                i= i*base + d;
                    341:        }
                    342:        return i;
                    343: }
                    344: 
                    345: Hidden string getstring()
                    346: {
                    347:        char buf[256]; /* Arbitrary limit */
                    348:        char quote= nextc;
                    349:        char c;
                    350:        int len= 0;
                    351: 
                    352:        adv();
                    353:        while (nextc != quote) {
                    354:                if (nextc == '\n') {
                    355:                        err("closing string quote not found", "");
                    356:                        return NULL;
                    357:                }
                    358:                if (nextc != '\\') {
                    359:                        c= nextc;
                    360:                        adv();
                    361:                }
                    362:                else {
                    363:                        adv();
                    364:                        switch (nextc) {
                    365: 
                    366:                        case 'r': c= '\r'; adv(); break;
                    367:                        case 'n': c= '\n'; adv(); break;
                    368:                        case 'b': c= '\b'; adv(); break;
                    369:                        case 't': c= '\t'; adv(); break;
                    370:                        case 'f': c= '\f'; adv(); break;
                    371: 
                    372:                        case 'E':
                    373:                        case 'e': c= ESC; adv(); break;
                    374: 
                    375:                        case '0': case '1': case '2': case '3':
                    376:                        case '4': case '5': case '6': case '7':
                    377:                                c= nextc-'0';
                    378:                                adv();
                    379:                                if (nextc >= '0' && nextc < '8') {
                    380:                                        c= 8*c + nextc-'0';
                    381:                                        adv();
                    382:                                        if (nextc >= '0' && nextc < '8') {
                    383:                                                c= 8*c + nextc-'0';
                    384:                                                adv();
                    385:                                        }
                    386:                                }
                    387:                                break;
                    388: 
                    389:                        default: c=nextc; adv(); break;
                    390: 
                    391:                        }
                    392:                }
                    393:                if (len >= sizeof buf) {
                    394:                        err("string too long", "");
                    395:                        return NULL;
                    396:                }
                    397:                buf[len++]= c;
                    398:        }
                    399:        adv();
                    400:        buf[len]= '\0';
                    401:        return savestr(buf);
                    402: }
                    403: 
                    404: Hidden string getitem()
                    405: {
                    406:        char buf[2];
                    407:        string keyname;
                    408:        int i;
                    409: 
                    410:        switch (nextc) {
                    411:        case '"':
                    412:        case '\'':
                    413:                return getstring();
                    414:        case '^':
                    415:                adv();
                    416:                if (isalpha(nextc) || index("@^_[]\\?", nextc)) {
                    417:                        if (nextc == '?')
                    418:                                buf[0]= '\177';
                    419:                        else
                    420:                                buf[0]= nextc & 037;
                    421:                        buf[1]= '\0';
                    422:                        adv();
                    423:                        return savestr(buf);
                    424:                }
                    425:                err("Invalid character after '^'", "");
                    426:                return NULL;
                    427:        default:
                    428:                if (isdigit(nextc)) {
                    429:                        buf[0]= getnumber();
                    430:                        buf[1]= '\0';
                    431:                        return savestr(buf);
                    432:                }
                    433:                if (isalpha(nextc) || nextc == '_') {
                    434:                        keyname= getname(); /* Cannot fail */
                    435:                        if (strlen(keyname) == 1)
                    436:                                return savestr(keyname);
                    437:                                /* Single letters stand for themselves */
                    438:                        i= lookup(keyname);
                    439:                        if (i < 0 || deftab[i].code <= 0) {
                    440:                                err("%s: not a key name", keyname);
                    441:                                freemem(keyname);
                    442:                                return NULL;
                    443:                        }
                    444:                        else if (deftab[i].def == NULL) {
                    445:                                err("%s: undefined key", keyname);
                    446:                                freemem(keyname);
                    447:                                return NULL;
                    448:                        }
                    449:                        else
                    450:                                return savestr(deftab[i].def);
                    451:                }
                    452:                err("Invalid item", "");
                    453:                return NULL;
                    454:        }
                    455: }
                    456: 
                    457: Hidden string getrhs()
                    458: {
                    459:        string first, item;
                    460: 
                    461:        skipsp();
                    462:        first= getitem();
                    463:        if (first != NULL) {
                    464:                for (;;) {
                    465:                        skipsp();
                    466:                        if (nextc == '\n' || nextc == COMMENT)
                    467:                                break;
                    468:                        item= getitem();
                    469:                        if (item == NULL) {
                    470:                                freemem(first);
                    471:                                return NULL;
                    472:                        }
                    473:                        append(&first, item);
                    474:                        freemem(item);
                    475:                }
                    476:        }
                    477:        return first;
                    478: }
                    479: 
                    480: Hidden Procedure getdef()
                    481: {
                    482:        string name;
                    483:        int key;
                    484:        string rhs;
                    485: 
                    486:        name= getname();
                    487:        if (name == NULL)
                    488:                return;
                    489:        skipsp();
                    490:        if (nextc != '=') {
                    491:                err("Command name %s not followed by '='", name);
                    492:                return;
                    493:        }
                    494:        key= lookup(name);
                    495:        if (key < 0) {
                    496:                err("Unknown command: %s", name);
                    497:                return;
                    498:        }
                    499:        if (deftab[key].code < 0) {
                    500:                err("No redefinition of %s allowed", name);
                    501:                return;
                    502:        }
                    503:        adv();
                    504:        rhs= getrhs();
                    505:        if (rhs != NULL)
                    506:                store(deftab[key].code, name, rhs);
                    507: }
                    508: 
                    509: Hidden Procedure getline()
                    510: {
                    511:        adv();
                    512:        skipsp();
                    513:        if (nextc != COMMENT && nextc != '\n')
                    514:                getdef();
                    515:        while (nextc != '\n')
                    516:                adv();
                    517: }
                    518: 
                    519: #ifndef NDEBUG
                    520: Hidden Procedure dump(where)
                    521:        string where;
                    522: {
                    523:        int i;
                    524:        string s;
                    525: 
                    526:        printf("\nDump of key definitions %s.\n\n", where);
                    527:        printf("Code    Name            Definition\n");
                    528:        for (i= 0; i < ndefs; ++i) {
                    529:                printf("%04o    ", deftab[i].code);
                    530:                if (deftab[i].name != NULL)
                    531:                        printf("%-15s ", deftab[i].name);
                    532:                else
                    533:                        printf("%16s", "");
                    534:                s= deftab[i].def;
                    535:                if (s != NULL) {
                    536:                        for (; *s != '\0'; ++s) {
                    537:                                if (isascii(*s) && (isprint(*s) || *s == ' '))
                    538:                                        fputc(*s, stdout);
                    539:                                else
                    540:                                        printf("\\%03o", *s&0377);
                    541:                        }
                    542:                }
                    543:                printf("\n");
                    544:        }
                    545:        fflush(stdout);
                    546: }
                    547: #endif !NDEBUG
                    548: 
                    549: Hidden Procedure countdefs()
                    550: {
                    551:        struct tabent *d;
                    552: 
                    553:        d= deftab;
                    554:        while (d->name != NULL || d->code != 0 || d->def != NULL) {
                    555:                ++d;
                    556:                if (d >= deftab+MAXDEFS)
                    557:                        syserr("too many predefined keys");
                    558:        }
                    559:        ndefs= d-deftab;
                    560: }
                    561: 
                    562: Hidden Procedure process()
                    563: {
                    564:        errcount= 0;
                    565:        lcount= 1;
                    566:        eof= No;
                    567:        do {
                    568:                getline();
                    569:        } while (!eof);
                    570: }
                    571: 
                    572: Hidden bool try(dir, file, type)
                    573:        string dir, file, type;
                    574: {
                    575:        char buffer[200];
                    576: 
                    577: #ifdef IBMPC
                    578:        sprintf(buffer, "%.150s\\%.9s%.3s", dir, file, type);
                    579: #else !IBMPC
                    580:        sprintf(buffer, "%.150s/%.20s%.20s", dir, file, type);
                    581: #endif !IBMPC
                    582:        fp= fopen(buffer, "r");
                    583:        if (fp == NULL)
                    584:                return No;
                    585:        filename= buffer;
                    586:        process();
                    587:        fclose(fp);
                    588: #ifndef NDEBUG
                    589:        if (dflag)
                    590:                dump("after try");
                    591: #endif NDEBUG
                    592:        return Yes;
                    593: }
                    594: 
                    595: #ifndef IBMPC
                    596: Hidden Procedure readtermcap()
                    597: {
                    598:        string tgetstr();
                    599:        char buffer[1024]; /* Constant dictated by termcap manual entry */
                    600:        static char area[1024];
                    601:        string endarea= area;
                    602:        string anentry;
                    603:        struct tabent *d, *last;
                    604: 
                    605:        switch (tgetent(buffer, getenv("TERM"))) {
                    606: 
                    607:        default:
                    608:                fprintf(stderr, "*** Bad tgetent() return value.\n");
                    609:                /* Fall through */
                    610:        case -1:
                    611:                fprintf(stderr, "*** Can't read termcap.\n");
                    612:                /* Fall through again */
                    613:        case 0:
                    614:                fprintf(stderr, "*** No description for your terminal.\n");
                    615:                exit(1);
                    616: 
                    617:        case 1:
                    618:                break;
                    619:        }
                    620:        last= deftab+ndefs;
                    621:        for (d= deftab; d < last; ++d) {
                    622:                if (d->def != NULL && d->def[0] == '=') {
                    623:                        anentry= tgetstr(d->def+1, &endarea);
                    624:                        if (anentry != NULL && anentry[0] != '\0')
                    625:                                d->def= anentry;
                    626:                        else
                    627:                                d->def= NULL;
                    628:                }
                    629:        }
                    630: }
                    631: #endif !IBMPC
                    632: 
                    633: Visible Procedure initkeys()
                    634: {
                    635:        string term= NULL;
                    636: 
                    637:        countdefs();
                    638: #ifndef NDEBUG
                    639:        if (dflag)
                    640:                dump("before termcap");
                    641: #endif NDEBUG
                    642: #ifndef IBMPC
                    643:        readtermcap();
                    644: #ifndef NDEBUG
                    645:        if (dflag)
                    646:                dump("after termcap");
                    647: #endif NDEBUG
                    648:        term= getenv("TERM");
                    649:        if (term != NULL && term[0] == '\0')
                    650:                term= NULL;
                    651: #endif !IBMPC
                    652: #ifdef DEBUG
                    653:        /* Try in the current directory. Only for debugging porpoises. */
                    654:        if (term != NULL)
                    655:                if (try(".", keyfile, term)) return;
                    656: #endif DEBUG
                    657:        if (term != NULL) {
                    658:                if (try(homedir, keyfile, term)) return;
                    659:                if (try(libdir, keyfile, term)) return;
                    660:        }
                    661: #ifdef DEBUG
                    662:        if (try(".", keyfile, deftype)) return;
                    663: #endif DEBUG
                    664:        if (try(homedir, keyfile, deftype)) return;
                    665:        if (try(libdir, keyfile, deftype)) return;
                    666: #ifndef NDEBUG
                    667:        printf("[No key definitions file found, using defaults.]\n");
                    668: #endif !NDEBUG
                    669: }
                    670: 
                    671: 
                    672: /* Output a named string to the terminal */
                    673: 
                    674: Hidden Procedure outstring(name)
                    675:        string name;
                    676: {
                    677:        int i= lookup(name);
                    678:        string def;
                    679: 
                    680:        if (i >= 0 && (def= deftab[i].def) != NULL)
                    681:                fputs(def, stdout);
                    682: }
                    683: 
                    684: 
                    685: /* Output the terminal's initialization sequence, if any. */
                    686: 
                    687: Visible Procedure
                    688: initgetc()
                    689: {
                    690:        outstring("term_init");
                    691: }
                    692: 
                    693: 
                    694: /* Output a sequence, if any, to return the terminal to a 'normal' state. */
                    695: 
                    696: Visible Procedure endgetc()
                    697: {
                    698:        outstring("term_done");
                    699: }
                    700: 
                    701: 
                    702: /* Read a command from the keyboard, decoding composite key definitions. */
                    703: 
                    704: #ifndef IBMPC
                    705: /* Strip high bit from input characters (matters only on PWB systems?) */
                    706: #define getch() (getchar() & 0177)
                    707: #endif !IBMPC
                    708: 
                    709: Visible int inchar()
                    710: {
                    711:        int c;
                    712:        struct tabent *d, *last;
                    713:        char buffer[100];
                    714:        int len;
                    715: 
                    716:        c= getch();
                    717:        if (c == EOF)
                    718:                return c;
                    719: #ifdef IBMPC
                    720:        if (c == 0)
                    721:                c= 0377;
                    722: #endif IBMPC
                    723:        last= deftab+ndefs;
                    724:        for (d= deftab; d < last; ++d) {
                    725:                if (d->code > 0 && d->def != NULL && c == (d->def[0] & 0377))
                    726:                        break;
                    727:        }
                    728:        if (d == last) {
                    729:                if (c == ESC) {
                    730:                        /* Kludge to make ESC-char by default equal to
                    731:                           char|MASK -- the command definitions do the rest:
                    732:                           e.g. WIDEN is 'w'|MASK, so ESC-w means WIDEN. */
                    733:                        c= getch();
                    734:                        if (c == EOF)
                    735:                                return EOF;
                    736:                        return (c&0177) | MASK;
                    737:                }
                    738:                return c;
                    739:        }
                    740:        if (d->def[1] == '\0')
                    741:                return d->code;
                    742:        buffer[0]= c;
                    743:        len= 1;
                    744:        for (;;) {
                    745:                c= getch();
                    746:                if (c == EOF)
                    747:                        return EOF;
                    748:                buffer[len]= c;
                    749:                if (len < sizeof buffer - 1)
                    750:                        ++len;
                    751:                for (d= deftab; d < last; ++d) {
                    752:                        if (d->code > 0 && d->def != NULL
                    753:                                && strncmp(buffer, d->def, len) == 0)
                    754:                                break;
                    755:                }
                    756:                if (d == last) {
                    757:                        if (buffer[0] == ESC && len == 2) {
                    758:                                /* Same kludge as above */
                    759:                                return c&0177 | MASK;
                    760:                        }
                    761:                        return 0377; /* Hope this rings a bell */
                    762:                }
                    763:                if (d->def[len] == '\0')
                    764:                        return d->code;
                    765:        }
                    766: }

unix.superglobalmegacorp.com

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