[BACK]Return to extend.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/extend.c, Revision 1.3

1.1       deraadt     1: /*
                      2:  *     Extended (M-X) commands, rebinding, and
                      3:  *     startup file processing.
                      4:  */
                      5: #include       "def.h"
                      6: #include       "kbd.h"
                      7:
                      8: #ifndef NO_MACRO
                      9: #include       "macro.h"
                     10: #endif
                     11:
                     12: #ifdef FKEYS
                     13: #include       "key.h"
                     14: #ifndef        NO_STARTUP
                     15: #ifndef        BINDKEY
                     16: #define        BINDKEY         /* bindkey is used by FKEYS startup code */
                     17: #endif
                     18: #endif
                     19: #endif
                     20:
                     21: extern int rescan();
                     22:
                     23: /* insert a string, mainly for use from macros (created by selfinsert) */
                     24: /*ARGSUSED*/
                     25: insert(f, n)
                     26: int f, n;
                     27: {
                     28:     register char *cp;
                     29:     char buf[128];
                     30: #ifndef NO_MACRO
                     31:     register int count;
                     32:     int c;
                     33:
                     34:     if(inmacro) {
                     35:        while(--n >= 0) {
                     36:            for(count = 0; count < maclcur->l_used; count++) {
                     37:                if((((c=maclcur->l_text[count]) == '\n') ? lnewline()
                     38:                    : linsert(1, c)) != TRUE) return FALSE;
                     39:            }
                     40:        }
                     41:        maclcur = maclcur->l_fp;
                     42:        return TRUE;
                     43:     }
                     44:     if(n==1) thisflag |= CFINS; /* CFINS means selfinsert can tack on end */
                     45: #endif
                     46:     if(eread("Insert: ", buf, sizeof(buf), EFNEW) == FALSE) return FALSE;
                     47:     while(--n >= 0) {
                     48:        cp = buf;
                     49:        while(*cp) {
                     50:            if(((*cp == '\n') ? lnewline() : linsert(1, *cp)) != TRUE)
                     51:                return FALSE;
                     52:            cp++;
                     53:        }
                     54:     }
                     55:     return TRUE;
                     56: }
                     57:
                     58: /*
                     59:  * Bind a key to a function.  Cases range from the trivial (replacing an
                     60:  * existing binding) to the extremly complex (creating a new prefix in a
                     61:  * map_element that already has one, so the map_element must be split,
                     62:  * but the keymap doesn't have enough room for another map_element, so
                     63:  * the keymap is reallocated). No attempt is made to reclaim space no
                     64:  * longer used, if this is a problem flags must be added to indicate
                     65:  * malloced verses static storage in both keymaps and map_elements.
                     66:  * Structure assignments would come in real handy, but K&R based compilers
                     67:  * don't have them.  Care is taken so running out of memory will leave
                     68:  * the keymap in a usable state.
                     69:  */
                     70: static int remap(curmap, c, funct, pref_map)
                     71: register KEYMAP        *curmap;/* pointer to the map being changed */
                     72: int    c;              /* character being changed */
                     73: PF     funct;          /* function being changed to */
                     74: KEYMAP *pref_map;      /* if funct==prefix, map to bind to or NULL for new */
                     75: /* extern MAP_ELEMENT *ele;    must be set before calling */
                     76: {
                     77:        register int i;
                     78:        int     n1, n2, nold;
                     79:        KEYMAP  *mp;
                     80:        PF      *pfp;
                     81:        MAP_ELEMENT *mep;
                     82:        static  KEYMAP *realocmap();
                     83:
                     84:        if(ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
                     85:            if(ele > &curmap->map_element[0] && (funct!=prefix ||
                     86:                        (ele-1)->k_prefmap==NULL)) {
                     87:                n1 = c - (ele-1)->k_num;
                     88:            } else n1 = HUGE;
                     89:            if(ele < &curmap->map_element[curmap->map_num] && (funct!=prefix ||
                     90:                        ele->k_prefmap==NULL)) {
                     91:                n2 = ele->k_base - c;
                     92:            } else n2 = HUGE;
                     93:            if(n1 <= MAPELEDEF && n1 <= n2) {
                     94:                ele--;
                     95:                if((pfp = (PF *)malloc((unsigned)(c - ele->k_base+1)
                     96:                        * sizeof(PF))) == NULL) {
                     97:                    ewprintf("Out of memory");
                     98:                    return FALSE;
                     99:                }
                    100:                nold = ele->k_num - ele->k_base + 1;
                    101:                for(i=0; i < nold; i++)
                    102:                    pfp[i] = ele->k_funcp[i];
                    103:                while(--n1) pfp[i++] = curmap->map_default;
                    104:                pfp[i] = funct;
                    105:                ele->k_num = c;
                    106:                ele->k_funcp = pfp;
                    107:            } else if(n2 <= MAPELEDEF) {
                    108:                if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + 1)
                    109:                        * sizeof(PF))) == NULL) {
                    110:                    ewprintf("Out of memory");
                    111:                    return FALSE;
                    112:                }
                    113:                nold = ele->k_num - ele->k_base + 1;
                    114:                for(i=0; i < nold; i++)
                    115:                    pfp[i+n2] = ele->k_funcp[i];
                    116:                while(--n2) pfp[n2] = curmap->map_default;
                    117:                pfp[0] = funct;
                    118:                ele->k_base = c;
                    119:                ele->k_funcp = pfp;
                    120:            } else {
                    121:                if(curmap->map_num >= curmap->map_max &&
                    122:                    (curmap = realocmap(curmap)) == NULL) return FALSE;
                    123:                if((pfp = (PF *)malloc(sizeof(PF))) == NULL) {
                    124:                    ewprintf("Out of memory");
                    125:                    return FALSE;
                    126:                }
                    127:                pfp[0] = funct;
                    128:                for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
                    129:                    mep->k_base    = (mep-1)->k_base;
                    130:                    mep->k_num     = (mep-1)->k_num;
                    131:                    mep->k_funcp   = (mep-1)->k_funcp;
                    132:                    mep->k_prefmap = (mep-1)->k_prefmap;
                    133:                }
                    134:                ele->k_base = c;
                    135:                ele->k_num = c;
                    136:                ele->k_funcp = pfp;
                    137:                ele->k_prefmap = NULL;
                    138:                curmap->map_num++;
                    139:            }
                    140:            if(funct == prefix) {
                    141:                if(pref_map != NULL) {
                    142:                    ele->k_prefmap = pref_map;
                    143:                } else {
                    144:                    if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
                    145:                            (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
                    146:                        ewprintf("Out of memory");
                    147:                        ele->k_funcp[c - ele->k_base] = curmap->map_default;
                    148:                        return FALSE;
                    149:                    }
                    150:                    mp->map_num = 0;
                    151:                    mp->map_max = MAPINIT;
                    152:                    mp->map_default = rescan;
                    153:                    ele->k_prefmap = mp;
                    154:                }
                    155:            }
                    156:        } else {
                    157:            n1 = c - ele->k_base;
                    158:            if(ele->k_funcp[n1] == funct && (funct!=prefix || pref_map==NULL ||
                    159:                    pref_map==ele->k_prefmap))
                    160:                return TRUE;    /* no change */
                    161:            if(funct!=prefix || ele->k_prefmap==NULL) {
                    162:                if(ele->k_funcp[n1] == prefix)
                    163:                    ele->k_prefmap = (KEYMAP *)NULL;
                    164:                ele->k_funcp[n1] = funct;       /* easy case */
                    165:                if(funct==prefix) {
                    166:                    if(pref_map!=NULL)
                    167:                        ele->k_prefmap = pref_map;
                    168:                    else {
                    169:                        if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
                    170:                                (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
                    171:                            ewprintf("Out of memory");
                    172:                            ele->k_funcp[c - ele->k_base] = curmap->map_default;
                    173:                            return FALSE;
                    174:                        }
                    175:                        mp->map_num = 0;
                    176:                        mp->map_max = MAPINIT;
                    177:                        mp->map_default = rescan;
                    178:                        ele->k_prefmap = mp;
                    179:                    }
                    180:                }
                    181:            } else {
                    182:                /* this case is the splits */
                    183:                /* determine which side of the break c goes on */
                    184:                /* 0 = after break; 1 = before break */
                    185:                n2 = 1;
                    186:                for(i=0; n2 && i < n1; i++)
                    187:                        n2 &= ele->k_funcp[i] != prefix;
                    188:                if(curmap->map_num >= curmap->map_max &&
                    189:                    (curmap = realocmap(curmap)) == NULL) return FALSE;
                    190:                if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + !n2)
                    191:                        * sizeof(PF))) == NULL) {
                    192:                    ewprintf("Out of memory");
                    193:                    return FALSE;
                    194:                }
                    195:                ele->k_funcp[n1] = prefix;
                    196:                for(i=n1+n2; i <= ele->k_num - ele->k_base; i++)
                    197:                    pfp[i-n1-n2] = ele->k_funcp[i];
                    198:                for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
                    199:                    mep->k_base    = (mep-1)->k_base;
                    200:                    mep->k_num     = (mep-1)->k_num;
                    201:                    mep->k_funcp   = (mep-1)->k_funcp;
                    202:                    mep->k_prefmap = (mep-1)->k_prefmap;
                    203:                }
                    204:                ele->k_num = c - !n2;
                    205:                (ele+1)->k_base = c + n2;
                    206:                (ele+1)->k_funcp = pfp;
                    207:                ele += !n2;
                    208:                ele->k_prefmap = NULL;
                    209:                curmap->map_num++;
                    210:                if(pref_map == NULL) {
                    211:                    if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
                    212:                            (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
                    213:                        ewprintf("Out of memory");
                    214:                        ele->k_funcp[c - ele->k_base] = curmap->map_default;
                    215:                        return FALSE;
                    216:                    }
                    217:                    mp->map_num = 0;
                    218:                    mp->map_max = MAPINIT;
                    219:                    mp->map_default = rescan;
                    220:                    ele->k_prefmap = mp;
                    221:                } else ele->k_prefmap = pref_map;
                    222:            }
                    223:        }
                    224:        return TRUE;
                    225: }
                    226:
                    227: /* reallocate a keymap, used above */
                    228: static KEYMAP *realocmap(curmap)
                    229: register KEYMAP *curmap;
                    230: {
                    231:     register KEYMAP *mp;
                    232:     register int i;
                    233:     static VOID fixmap();
                    234:     extern int nmaps;
                    235:
                    236:     if((mp = (KEYMAP *)malloc((unsigned)(sizeof(KEYMAP)+
                    237:            (curmap->map_max+(MAPGROW-1))*sizeof(MAP_ELEMENT)))) == NULL) {
                    238:        ewprintf("Out of memory");
                    239:        return NULL;
                    240:     }
                    241:     mp->map_num = curmap->map_num;
                    242:     mp->map_max = curmap->map_max + MAPGROW;
                    243:     mp->map_default = curmap->map_default;
                    244:     for(i=curmap->map_num; i--; ) {
                    245:        mp->map_element[i].k_base       = curmap->map_element[i].k_base;
                    246:        mp->map_element[i].k_num        = curmap->map_element[i].k_num;
                    247:        mp->map_element[i].k_funcp      = curmap->map_element[i].k_funcp;
                    248:        mp->map_element[i].k_prefmap    = curmap->map_element[i].k_prefmap;
                    249:     }
                    250:     for(i=nmaps; i--; ) {
                    251:        if(map_table[i].p_map == curmap) map_table[i].p_map = mp;
                    252:        else fixmap(curmap, mp, map_table[i].p_map);
                    253:     }
                    254:     ele = &mp->map_element[ele - &curmap->map_element[0]];
                    255:     return mp;
                    256: }
                    257:
                    258: /* fix references to a reallocated keymap (recursive) */
                    259: static VOID fixmap(curmap, mp, mt)
                    260: register KEYMAP *mt;
                    261: register KEYMAP *curmap;
                    262: KEYMAP *mp;
                    263: {
                    264:     register int i;
                    265:
                    266:     for(i = mt->map_num; i--; ) {
                    267:        if(mt->map_element[i].k_prefmap != NULL) {
                    268:            if(mt->map_element[i].k_prefmap == curmap)
                    269:                mt->map_element[i].k_prefmap = mp;
                    270:            else fixmap(curmap, mp, mt->map_element[i].k_prefmap);
                    271:        }
                    272:     }
                    273: }
                    274:
                    275: /*
                    276:  * do the input for local-set-key, global-set-key  and define-key
                    277:  * then call remap to do the work.
                    278:  */
                    279:
                    280: static int dobind(curmap, p, unbind)
                    281: register KEYMAP *curmap;
                    282: char *p;
                    283: int unbind;
                    284: {
                    285:        PF      funct;
                    286:        char    prompt[80];
                    287:        char    *pep;
                    288:        int     c;
                    289:        int     s;
                    290:        KEYMAP  *pref_map = NULL;
                    291:
                    292: #ifndef NO_MACRO
                    293:        if(macrodef) {
                    294:        /* keystrokes arn't collected.  Not hard, but pretty useless */
                    295:        /* would not work for function keys in any case */
                    296:            ewprintf("Can't rebind key in macro");
                    297:            return FALSE;
                    298:        }
                    299: #ifndef NO_STARTUP
                    300:        if(inmacro) {
                    301:            for(s=0; s < maclcur->l_used - 1; s++) {
                    302:                if(doscan(curmap, c=CHARMASK(maclcur->l_text[s])) != prefix) {
                    303:                    if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE) {
                    304:                        return FALSE;
                    305:                    }
                    306:                }
                    307:                curmap = ele->k_prefmap;
                    308:            }
                    309:            (VOID) doscan(curmap, c=maclcur->l_text[s]);
                    310:            maclcur = maclcur->l_fp;
                    311:        } else {
                    312: #endif
                    313: #endif
                    314:            (VOID) strcpy(prompt, p);
                    315:            pep = prompt + strlen(prompt);
                    316:            for(;;) {
                    317:                ewprintf("%s", prompt);
                    318:                pep[-1] = ' ';
                    319:                pep = keyname(pep, c = getkey(FALSE));
                    320:                if(doscan(curmap,c) != prefix) break;
                    321:                *pep++ = '-';
                    322:                *pep = '\0';
                    323:                curmap = ele->k_prefmap;
                    324:            }
                    325: #ifndef NO_STARTUP
                    326:        }
                    327: #endif
                    328:        if(unbind) funct = rescan;
                    329:        else {
                    330:            if ((s=eread("%s to command: ", prompt, 80, EFFUNC|EFNEW, prompt))
                    331:                        != TRUE) return s;
                    332:            if (((funct = name_function(prompt)) == prefix) ?
                    333:                        (pref_map = name_map(prompt)) == NULL : funct==NULL) {
                    334:                ewprintf("[No match]");
                    335:                return FALSE;
                    336:            }
                    337:        }
                    338:        return remap(curmap, c, funct, pref_map);
                    339: }
                    340:
                    341: /*
                    342:  * bindkey: bind key sequence to a function in
                    343:  * the specified map.  Used by excline so it can bind function keys.
                    344:  * To close to release to change calling sequence, should just pass
                    345:  * KEYMAP *curmap rather than KEYMAP **mapp.
                    346: */
                    347: #ifdef BINDKEY
                    348: bindkey(mapp, fname, keys, kcount)
                    349: KEYMAP **mapp;
                    350: char *fname;
                    351: KCHAR *keys;
                    352: int kcount;
                    353: {
                    354:        KEYMAP  *curmap = *mapp;
                    355:        PF      funct;
                    356:        int     c;
                    357:        KEYMAP  *pref_map = NULL;
                    358:
                    359:        if(fname == NULL) funct = rescan;
                    360:        else if (((funct = name_function(fname)) == prefix) ?
                    361:                (pref_map = name_map(fname)) == NULL : funct==NULL) {
                    362:            ewprintf("[No match: %s]", fname);
                    363:            return FALSE;
                    364:        }
                    365:        while(--kcount) {
                    366:            if(doscan(curmap, c = *keys++) != prefix) {
                    367:                if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE)
                    368:                    return FALSE;
                    369:            }
                    370:            curmap = ele->k_prefmap;
                    371:        }
                    372:        (VOID) doscan(curmap, c = *keys);
                    373:        return remap(curmap, c, funct, pref_map);
                    374: }
1.3     ! millert   375:
        !           376: #ifdef FKEYS
        !           377: /*
        !           378:  * Wrapper for bindkey() that converts escapes.
        !           379:  */
        !           380: int
        !           381: dobindkey(map, func, str)
        !           382:        KEYMAP *map;
        !           383:        char *func;
        !           384:        char *str;
        !           385: {
        !           386:        int i;
        !           387:
        !           388:        for (i = 0; *str && i < MAXKEY; i++) {
        !           389:                /* XXX - convert numbers w/ strol()? */
        !           390:                if (*str != '\\')
        !           391:                        key.k_chars[i] = *str;
        !           392:                else {
        !           393:                        switch(*++str) {
        !           394:                        case 't': case 'T':
        !           395:                                key.k_chars[i] = '\t';
        !           396:                                break;
        !           397:                        case 'n': case 'N':
        !           398:                                key.k_chars[i] = '\n';
        !           399:                                break;
        !           400:                        case 'r': case 'R':
        !           401:                                key.k_chars[i] = '\r';
        !           402:                                break;
        !           403:                        case 'e': case 'E':
        !           404:                                key.k_chars[i] = CCHR('[');
        !           405:                                break;
        !           406:                        }
        !           407:                }
        !           408:                str++;
        !           409:        }
        !           410:        key.k_count = i;
        !           411:        return(bindkey(&map, func, key.k_chars, key.k_count));
        !           412: }
        !           413: #endif
1.1       deraadt   414: #endif
                    415:
                    416: /*
                    417:  * This function modifies the fundamental keyboard map.
                    418:  */
                    419: /*ARGSUSED*/
                    420: bindtokey(f, n)
                    421: {
                    422:     return dobind(map_table[0].p_map, "Global set key: ", FALSE);
                    423: }
                    424:
                    425: /*
                    426:  * This function modifies the current mode's keyboard map.
                    427:  */
                    428: /*ARGSUSED*/
                    429: localbind(f, n)
                    430: {
                    431:     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local set key: ",
                    432:        FALSE);
                    433: }
                    434:
                    435: /*
                    436:  * This function redefines a key in any keymap.
                    437:  */
                    438: /*ARGSUSED*/
                    439: define_key(f, n)
                    440: {
                    441:     static char buf[48] = "Define key map: ";
                    442:     MAPS *mp;
                    443:     char *strncat();
                    444:
                    445:     buf[16] = '\0';
                    446:     if(eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE) return FALSE;
                    447:     if((mp = name_mode(&buf[16])) == NULL) {
                    448:        ewprintf("Unknown map %s", &buf[16]);
                    449:        return FALSE;
                    450:     }
                    451:     (VOID) strncat(&buf[16], " key: ", 48-16-1);
                    452:     return dobind(mp->p_map, buf, FALSE);
                    453: }
                    454:
                    455: unbindtokey(f, n)
                    456: int f, n;
                    457: {
                    458:     return dobind(map_table[0].p_map, "Global unset key: ", TRUE);
                    459: }
                    460:
                    461: localunbind(f, n)
                    462: int f, n;
                    463: {
                    464:     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local unset key: ",
                    465:        TRUE);
                    466: }
                    467:
                    468: /*
                    469:  * Extended command. Call the message line
                    470:  * routine to read in the command name and apply autocompletion
                    471:  * to it. When it comes back, look the name up in the symbol table
                    472:  * and run the command if it is found.
                    473:  * Print an error if there is anything wrong.
                    474:  */
                    475: extend(f, n)
                    476: {
                    477:        PF      funct;
                    478:        int     s;
                    479:        char    xname[NXNAME];
                    480:
                    481:        if(!(f & FFARG)) s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC);
                    482:        else             s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC, n);
                    483:        if(s != TRUE) return s;
                    484:        if((funct = name_function(xname)) != NULL) {
                    485: #ifndef NO_MACRO
                    486:            if(macrodef) {
                    487:                LINE *lp = maclcur;
                    488:                macro[macrocount-1].m_funct = funct;
                    489:                maclcur = lp->l_bp;
                    490:                maclcur->l_fp = lp->l_fp;
                    491:                free((char *)lp);
                    492:            }
                    493: #endif
                    494:            return (*funct)(f, n);
                    495:        }
                    496:        ewprintf("[No match]");
                    497:        return FALSE;
                    498: }
                    499:
                    500: #ifndef NO_STARTUP
                    501: /*
                    502:  * Define the commands needed to do startup-file processing.
                    503:  * This code is mostly a kludge just so we can get startup-file processing.
                    504:  *
                    505:  * If you're serious about having this code, you should rewrite it.
                    506:  * To wit:
                    507:  *     It has lots of funny things in it to make the startup-file look
                    508:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    509:  *     This should all vanish.
                    510:  *
                    511:  * We define eval-expression because it's easy.         It can make
                    512:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    513:  * useless.
                    514:  */
                    515:
                    516: /*
                    517:  * evalexpr - get one line from the user, and run it.
                    518:  */
                    519: /*ARGSUSED*/
                    520: evalexpr(f, n)
                    521: {
                    522:        int     s;
                    523:        char    exbuf[128];
                    524:
                    525:        if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
                    526:                return s;
                    527:        return excline(exbuf);
                    528: }
                    529: /*
                    530:  * evalbuffer - evaluate the current buffer as line commands. Useful
                    531:  *     for testing startup files.
                    532:  */
                    533: /*ARGSUSED*/
                    534: evalbuffer(f, n)
                    535: {
                    536:        register LINE   *lp;
                    537:        register BUFFER *bp = curbp;
                    538:        register int    s;
                    539:        static char     excbuf[128];
                    540:
                    541:        for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
                    542:                if (llength(lp) >= 128) return FALSE;
                    543:                (VOID) strncpy(excbuf, ltext(lp), llength(lp));
                    544:                excbuf[llength(lp)] = '\0';     /* make sure it's terminated */
                    545:                if ((s = excline(excbuf)) != TRUE) return s;
                    546:        }
                    547:        return TRUE;
                    548: }
                    549: /*
                    550:  * evalfile - go get a file and evaluate it as line commands. You can
                    551:  *     go get your own startup file if need be.
                    552:  */
                    553: /*ARGSUSED*/
                    554: evalfile(f, n)
                    555: {
                    556:        register int    s;
                    557:        char            fname[NFILEN];
                    558:
                    559:        if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
                    560:                return s;
                    561:        return load(fname);
                    562: }
                    563:
                    564: /*
                    565:  * load - go load the file name we got passed.
                    566:  */
                    567: load(fname) char *fname; {
                    568:        int     s = TRUE;
                    569:        int     nbytes;
                    570:        char    excbuf[128];
                    571:
                    572:        if ((fname = adjustname(fname)) == NULL)
                    573:                return FALSE;   /* just to be careful */
                    574:
                    575:        if (ffropen(fname, (BUFFER *) NULL) != FIOSUC) return FALSE;
                    576:        while ((s = ffgetline(excbuf, sizeof(excbuf)-1, &nbytes)) == FIOSUC) {
                    577:                excbuf[nbytes] = '\0';
                    578:                if (excline(excbuf) != TRUE) {
                    579:                        s = FIOERR;
                    580:                        ewprintf("Error loading file %s", fname);
                    581:                        break;
                    582:                }
                    583:        }
                    584:        (VOID) ffclose((BUFFER *) NULL);
                    585:        excbuf[nbytes] = '\0';
                    586:        if(s!=FIOEOF || (nbytes && excline(excbuf)!=TRUE))
                    587:                return FALSE;
                    588:        return TRUE;
                    589: }
                    590:
                    591: /*
                    592:  * excline - run a line from a load file or eval-expression.
                    593:  * if FKEYS is defined, duplicate functionallity of dobind so function
                    594:  * key values don't have to fit in type char.
                    595:  */
                    596: excline(line)
                    597: register char *line;
                    598: {
                    599:        register char   *funcp, *argp = NULL;
                    600:        register int    c;
                    601:        int             status;
                    602:        int     f, n;
                    603:        LINE    *lp, *np;
                    604:        PF      fp;
                    605: #ifdef FKEYS
                    606:        int     bind;
                    607:        KEYMAP  *curmap;
                    608:        MAPS    *mp;
                    609: #define BINDARG                0       /* this arg is key to bind (local/global set key) */
                    610: #define        BINDNO          1       /* not binding or non-quoted BINDARG */
                    611: #define BINDNEXT       2       /* next arg " (define-key) */
                    612: #define BINDDO         3       /* already found key to bind */
                    613: #define BINDEXT 1              /* space for trailing \0 */
                    614: #else
                    615: #define BINDEXT 0
                    616: #endif
                    617:        PF      name_function();
                    618:        LINE    *lalloc();
                    619:        static  char    *skipwhite(), *parsetoken();
                    620:
                    621:        if(macrodef || inmacro) {
                    622:                ewprintf("Not now!");
                    623:                return FALSE;
                    624:        }
                    625:
                    626:        f = 0;
                    627:        n = 1;
                    628:        funcp = skipwhite(line);
                    629:        if (*funcp == '\0') return TRUE;        /* No error on blank lines */
                    630:        line = parsetoken(funcp);
                    631:        if (*line != '\0') {
                    632:                *line++ = '\0';
                    633:                line = skipwhite(line);
                    634:                if ((*line >= '0' && *line <= '9') || *line == '-') {
                    635:                        argp = line;
                    636:                        line = parsetoken(line);
                    637:                }
                    638:        }
                    639:
                    640:        if (argp != NULL) {
                    641:                f = FFARG;
                    642:                n = atoi(argp);
                    643:        }
                    644:        if((fp = name_function(funcp)) == NULL) {
                    645:            ewprintf("Unknown function: %s", funcp);
                    646:            return FALSE;
                    647:        }
                    648: #ifdef FKEYS
                    649:        if(fp == bindtokey || fp == unbindtokey) {
                    650:                bind = BINDARG;
                    651:                curmap = map_table[0].p_map;
                    652:        } else if(fp == localbind || fp == localunbind) {
                    653:                bind = BINDARG;
                    654:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
                    655:        } else if(fp == define_key) bind = BINDNEXT;
                    656:        else bind = BINDNO;
                    657: #endif
                    658:        /* Pack away all the args now...        */
                    659:        if((np = lalloc(0))==FALSE) return FALSE;
                    660:        np->l_fp = np->l_bp = maclcur = np;
                    661:        while (*line != '\0') {
                    662:                argp = skipwhite(line);
                    663:                if (*argp == '\0') break;
                    664:                line = parsetoken(argp);
                    665:                if (*argp != '"') {
                    666:                    if (*argp == '\'') ++argp;
                    667:                    if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
                    668:                        status = FALSE;
                    669:                        goto cleanup;
                    670:                    }
                    671:                    bcopy(argp, ltext(lp), (int)(line-argp));
                    672: #ifdef FKEYS
                    673:                    lp->l_used--;       /* don't count BINDEXT! */
                    674:                    if(bind == BINDARG) bind = BINDNO;
                    675: #endif
                    676:                } else {        /* Quoted strings special */
                    677:                    ++argp;
                    678: #ifdef FKEYS
                    679:                    if(bind != BINDARG) {
                    680: #endif
                    681:                        if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
                    682:                            status = FALSE;
                    683:                            goto cleanup;
                    684:                        }
                    685:                        lp->l_used = 0;
                    686: #ifdef FKEYS
                    687:                    } else {
                    688:                        key.k_count = 0;
                    689:                    }
                    690: #endif
                    691:                    while (*argp != '"' && *argp != '\0') {
                    692:                        if (*argp != '\\') c = *argp++;
                    693:                        else {
                    694:                            switch(*++argp) {
                    695:                                case 't': case 'T':
                    696:                                    c = CCHR('I');
                    697:                                    break;
                    698:                                case 'n': case 'N':
                    699:                                    c = CCHR('J');
                    700:                                    break;
                    701:                                case 'r': case 'R':
                    702:                                    c = CCHR('M');
                    703:                                    break;
                    704:                                case 'e': case 'E':
                    705:                                    c = CCHR('[');
                    706:                                    break;
                    707:                                case '^':
                    708: /* split into two statements due to bug in OSK cpp */
                    709:                                    c = CHARMASK(*++argp);
                    710:                                    c = ISLOWER(c) ?
                    711:                                        CCHR(TOUPPER(c)) : CCHR(c);
                    712:                                    break;
                    713:                                case '0': case '1': case '2': case '3':
                    714:                                case '4': case '5': case '6': case '7':
                    715:                                    c = *argp - '0';
                    716:                                    if(argp[1] <= '7' && argp[1] >= '0') {
                    717:                                        c <<= 3;
                    718:                                        c += *++argp - '0';
                    719:                                        if(argp[1] <= '7' && argp[1] >= '0') {
                    720:                                            c <<= 3;
                    721:                                            c += *++argp - '0';
                    722:                                        }
                    723:                                    }
                    724:                                    break;
                    725: #ifdef FKEYS
                    726:                                case 'f': case 'F':
                    727:                                    c = *++argp - '0';
                    728:                                    if(ISDIGIT(argp[1])) {
                    729:                                        c *= 10;
                    730:                                        c += *++argp - '0';
                    731:                                    }
                    732:                                    c += KFIRST;
                    733:                                    break;
                    734: #endif
                    735:                                default:
                    736:                                    c = CHARMASK(*argp);
                    737:                                    break;
                    738:                            }
                    739:                            argp++;
                    740:                        }
                    741: #ifdef FKEYS
                    742:                        if(bind == BINDARG)
                    743:                            key.k_chars[key.k_count++] = c;
                    744:                        else
                    745: #endif
                    746:                            lp->l_text[lp->l_used++] = c;
                    747:                    }
                    748:                    if(*line) line++;
                    749:                }
                    750: #ifdef FKEYS
                    751:                switch(bind) {
                    752:                    case BINDARG:
                    753:                        bind = BINDDO;
                    754:                        break;
                    755:                    case BINDNEXT:
                    756:                        lp->l_text[lp->l_used] = '\0';
                    757:                        if((mp = name_mode(lp->l_text)) == NULL) {
                    758:                            ewprintf("No such mode: %s", lp->l_text);
                    759:                            status = FALSE;
                    760:                            free((char *)lp);
                    761:                            goto cleanup;
                    762:                        }
                    763:                        curmap = mp->p_map;
                    764:                        free((char *)lp);
                    765:                        bind = BINDARG;
                    766:                        break;
                    767:                    default:
                    768: #endif
                    769:                        lp->l_fp = np->l_fp;
                    770:                        lp->l_bp = np;
                    771:                        np->l_fp = lp;
                    772:                        np = lp;
                    773: #ifdef FKEYS
                    774:                }
                    775: #endif
                    776:        }
                    777: #ifdef FKEYS
                    778:        switch(bind) {
                    779:            default:
                    780:                ewprintf("Bad args to set key");
                    781:                status = FALSE;
                    782:                break;
                    783:            case BINDDO:
                    784:                if(fp != unbindtokey && fp != localunbind) {
                    785:                    lp->l_text[lp->l_used] = '\0';
                    786:                    status = bindkey(&curmap, lp->l_text, key.k_chars, key.k_count);
                    787:                } else status = bindkey(&curmap, (char *)NULL, key.k_chars, key.k_count);
                    788:                break;
                    789:            case BINDNO:
                    790: #endif
                    791:                inmacro = TRUE;
                    792:                maclcur = maclcur->l_fp;
                    793:                status = (*fp)(f, n);
                    794:                inmacro = FALSE;
                    795: #ifdef FKEYS
                    796:        }
                    797: #endif
                    798: cleanup:
                    799:        lp = maclcur->l_fp;
                    800:        while(lp!=maclcur) {
                    801:            np = lp->l_fp;
                    802:            free((char *)lp);
                    803:            lp = np;
                    804:        }
                    805:        free((char *)lp);
                    806:        return status;
                    807: }
                    808:
                    809: /*
                    810:  * a pair of utility functions for the above
                    811:  */
                    812: static char *
                    813: skipwhite(s)
                    814: register char *s;
                    815: {
                    816:        while(*s == ' ' || *s == '\t' || *s == ')' || *s == '(') s++;
                    817:        if (*s == ';') *s = '\0' ;
                    818:        return s;
                    819: }
                    820:
                    821: static char *
                    822: parsetoken(s)
                    823: register char *s;
                    824: {
                    825:        if (*s != '"') {
                    826:            while(*s && *s!=' ' && *s!='\t' && *s!=')' && *s!='(') s++;
                    827:            if(*s==';') *s='\0';
                    828:        } else
                    829:            do {        /* Strings get special treatment */
                    830:                        /* Beware: You can \ out the end of the string! */
                    831:                if (*s == '\\') ++s;
                    832:            } while (*++s != '"' && *s != '\0');
                    833:        return s;
                    834: }
                    835: #endif