Annotation of 43BSD/contrib/B/src/bed/getc.c, revision 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.