[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.1

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