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

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: }
                    375: #endif
                    376:
                    377: /*
                    378:  * This function modifies the fundamental keyboard map.
                    379:  */
                    380: /*ARGSUSED*/
                    381: bindtokey(f, n)
                    382: {
                    383:     return dobind(map_table[0].p_map, "Global set key: ", FALSE);
                    384: }
                    385:
                    386: /*
                    387:  * This function modifies the current mode's keyboard map.
                    388:  */
                    389: /*ARGSUSED*/
                    390: localbind(f, n)
                    391: {
                    392:     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local set key: ",
                    393:        FALSE);
                    394: }
                    395:
                    396: /*
                    397:  * This function redefines a key in any keymap.
                    398:  */
                    399: /*ARGSUSED*/
                    400: define_key(f, n)
                    401: {
                    402:     static char buf[48] = "Define key map: ";
                    403:     MAPS *mp;
                    404:     char *strncat();
                    405:
                    406:     buf[16] = '\0';
                    407:     if(eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE) return FALSE;
                    408:     if((mp = name_mode(&buf[16])) == NULL) {
                    409:        ewprintf("Unknown map %s", &buf[16]);
                    410:        return FALSE;
                    411:     }
                    412:     (VOID) strncat(&buf[16], " key: ", 48-16-1);
                    413:     return dobind(mp->p_map, buf, FALSE);
                    414: }
                    415:
                    416: unbindtokey(f, n)
                    417: int f, n;
                    418: {
                    419:     return dobind(map_table[0].p_map, "Global unset key: ", TRUE);
                    420: }
                    421:
                    422: localunbind(f, n)
                    423: int f, n;
                    424: {
                    425:     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local unset key: ",
                    426:        TRUE);
                    427: }
                    428:
                    429: /*
                    430:  * Extended command. Call the message line
                    431:  * routine to read in the command name and apply autocompletion
                    432:  * to it. When it comes back, look the name up in the symbol table
                    433:  * and run the command if it is found.
                    434:  * Print an error if there is anything wrong.
                    435:  */
                    436: extend(f, n)
                    437: {
                    438:        PF      funct;
                    439:        int     s;
                    440:        char    xname[NXNAME];
                    441:
                    442:        if(!(f & FFARG)) s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC);
                    443:        else             s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC, n);
                    444:        if(s != TRUE) return s;
                    445:        if((funct = name_function(xname)) != NULL) {
                    446: #ifndef NO_MACRO
                    447:            if(macrodef) {
                    448:                LINE *lp = maclcur;
                    449:                macro[macrocount-1].m_funct = funct;
                    450:                maclcur = lp->l_bp;
                    451:                maclcur->l_fp = lp->l_fp;
                    452:                free((char *)lp);
                    453:            }
                    454: #endif
                    455:            return (*funct)(f, n);
                    456:        }
                    457:        ewprintf("[No match]");
                    458:        return FALSE;
                    459: }
                    460:
                    461: #ifndef NO_STARTUP
                    462: /*
                    463:  * Define the commands needed to do startup-file processing.
                    464:  * This code is mostly a kludge just so we can get startup-file processing.
                    465:  *
                    466:  * If you're serious about having this code, you should rewrite it.
                    467:  * To wit:
                    468:  *     It has lots of funny things in it to make the startup-file look
                    469:  *     like a GNU startup file; mostly dealing with parens and semicolons.
                    470:  *     This should all vanish.
                    471:  *
                    472:  * We define eval-expression because it's easy.         It can make
                    473:  * *-set-key or define-key set an arbitrary key sequence, so it isn't
                    474:  * useless.
                    475:  */
                    476:
                    477: /*
                    478:  * evalexpr - get one line from the user, and run it.
                    479:  */
                    480: /*ARGSUSED*/
                    481: evalexpr(f, n)
                    482: {
                    483:        int     s;
                    484:        char    exbuf[128];
                    485:
                    486:        if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
                    487:                return s;
                    488:        return excline(exbuf);
                    489: }
                    490: /*
                    491:  * evalbuffer - evaluate the current buffer as line commands. Useful
                    492:  *     for testing startup files.
                    493:  */
                    494: /*ARGSUSED*/
                    495: evalbuffer(f, n)
                    496: {
                    497:        register LINE   *lp;
                    498:        register BUFFER *bp = curbp;
                    499:        register int    s;
                    500:        static char     excbuf[128];
                    501:
                    502:        for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
                    503:                if (llength(lp) >= 128) return FALSE;
                    504:                (VOID) strncpy(excbuf, ltext(lp), llength(lp));
                    505:                excbuf[llength(lp)] = '\0';     /* make sure it's terminated */
                    506:                if ((s = excline(excbuf)) != TRUE) return s;
                    507:        }
                    508:        return TRUE;
                    509: }
                    510: /*
                    511:  * evalfile - go get a file and evaluate it as line commands. You can
                    512:  *     go get your own startup file if need be.
                    513:  */
                    514: /*ARGSUSED*/
                    515: evalfile(f, n)
                    516: {
                    517:        register int    s;
                    518:        char            fname[NFILEN];
                    519:
                    520:        if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
                    521:                return s;
                    522:        return load(fname);
                    523: }
                    524:
                    525: /*
                    526:  * load - go load the file name we got passed.
                    527:  */
                    528: load(fname) char *fname; {
                    529:        int     s = TRUE;
                    530:        int     nbytes;
                    531:        char    excbuf[128];
                    532:
                    533:        if ((fname = adjustname(fname)) == NULL)
                    534:                return FALSE;   /* just to be careful */
                    535:
                    536:        if (ffropen(fname, (BUFFER *) NULL) != FIOSUC) return FALSE;
                    537:        while ((s = ffgetline(excbuf, sizeof(excbuf)-1, &nbytes)) == FIOSUC) {
                    538:                excbuf[nbytes] = '\0';
                    539:                if (excline(excbuf) != TRUE) {
                    540:                        s = FIOERR;
                    541:                        ewprintf("Error loading file %s", fname);
                    542:                        break;
                    543:                }
                    544:        }
                    545:        (VOID) ffclose((BUFFER *) NULL);
                    546:        excbuf[nbytes] = '\0';
                    547:        if(s!=FIOEOF || (nbytes && excline(excbuf)!=TRUE))
                    548:                return FALSE;
                    549:        return TRUE;
                    550: }
                    551:
                    552: /*
                    553:  * excline - run a line from a load file or eval-expression.
                    554:  * if FKEYS is defined, duplicate functionallity of dobind so function
                    555:  * key values don't have to fit in type char.
                    556:  */
                    557: excline(line)
                    558: register char *line;
                    559: {
                    560:        register char   *funcp, *argp = NULL;
                    561:        register int    c;
                    562:        int             status;
                    563:        int     f, n;
                    564:        LINE    *lp, *np;
                    565:        PF      fp;
                    566: #ifdef FKEYS
                    567:        int     bind;
                    568:        KEYMAP  *curmap;
                    569:        MAPS    *mp;
                    570: #define BINDARG                0       /* this arg is key to bind (local/global set key) */
                    571: #define        BINDNO          1       /* not binding or non-quoted BINDARG */
                    572: #define BINDNEXT       2       /* next arg " (define-key) */
                    573: #define BINDDO         3       /* already found key to bind */
                    574: #define BINDEXT 1              /* space for trailing \0 */
                    575: #else
                    576: #define BINDEXT 0
                    577: #endif
                    578:        PF      name_function();
                    579:        LINE    *lalloc();
                    580:        static  char    *skipwhite(), *parsetoken();
                    581:
                    582:        if(macrodef || inmacro) {
                    583:                ewprintf("Not now!");
                    584:                return FALSE;
                    585:        }
                    586:
                    587:        f = 0;
                    588:        n = 1;
                    589:        funcp = skipwhite(line);
                    590:        if (*funcp == '\0') return TRUE;        /* No error on blank lines */
                    591:        line = parsetoken(funcp);
                    592:        if (*line != '\0') {
                    593:                *line++ = '\0';
                    594:                line = skipwhite(line);
                    595:                if ((*line >= '0' && *line <= '9') || *line == '-') {
                    596:                        argp = line;
                    597:                        line = parsetoken(line);
                    598:                }
                    599:        }
                    600:
                    601:        if (argp != NULL) {
                    602:                f = FFARG;
                    603:                n = atoi(argp);
                    604:        }
                    605:        if((fp = name_function(funcp)) == NULL) {
                    606:            ewprintf("Unknown function: %s", funcp);
                    607:            return FALSE;
                    608:        }
                    609: #ifdef FKEYS
                    610:        if(fp == bindtokey || fp == unbindtokey) {
                    611:                bind = BINDARG;
                    612:                curmap = map_table[0].p_map;
                    613:        } else if(fp == localbind || fp == localunbind) {
                    614:                bind = BINDARG;
                    615:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
                    616:        } else if(fp == define_key) bind = BINDNEXT;
                    617:        else bind = BINDNO;
                    618: #endif
                    619:        /* Pack away all the args now...        */
                    620:        if((np = lalloc(0))==FALSE) return FALSE;
                    621:        np->l_fp = np->l_bp = maclcur = np;
                    622:        while (*line != '\0') {
                    623:                argp = skipwhite(line);
                    624:                if (*argp == '\0') break;
                    625:                line = parsetoken(argp);
                    626:                if (*argp != '"') {
                    627:                    if (*argp == '\'') ++argp;
                    628:                    if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
                    629:                        status = FALSE;
                    630:                        goto cleanup;
                    631:                    }
                    632:                    bcopy(argp, ltext(lp), (int)(line-argp));
                    633: #ifdef FKEYS
                    634:                    lp->l_used--;       /* don't count BINDEXT! */
                    635:                    if(bind == BINDARG) bind = BINDNO;
                    636: #endif
                    637:                } else {        /* Quoted strings special */
                    638:                    ++argp;
                    639: #ifdef FKEYS
                    640:                    if(bind != BINDARG) {
                    641: #endif
                    642:                        if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
                    643:                            status = FALSE;
                    644:                            goto cleanup;
                    645:                        }
                    646:                        lp->l_used = 0;
                    647: #ifdef FKEYS
                    648:                    } else {
                    649:                        key.k_count = 0;
                    650:                    }
                    651: #endif
                    652:                    while (*argp != '"' && *argp != '\0') {
                    653:                        if (*argp != '\\') c = *argp++;
                    654:                        else {
                    655:                            switch(*++argp) {
                    656:                                case 't': case 'T':
                    657:                                    c = CCHR('I');
                    658:                                    break;
                    659:                                case 'n': case 'N':
                    660:                                    c = CCHR('J');
                    661:                                    break;
                    662:                                case 'r': case 'R':
                    663:                                    c = CCHR('M');
                    664:                                    break;
                    665:                                case 'e': case 'E':
                    666:                                    c = CCHR('[');
                    667:                                    break;
                    668:                                case '^':
                    669: /* split into two statements due to bug in OSK cpp */
                    670:                                    c = CHARMASK(*++argp);
                    671:                                    c = ISLOWER(c) ?
                    672:                                        CCHR(TOUPPER(c)) : CCHR(c);
                    673:                                    break;
                    674:                                case '0': case '1': case '2': case '3':
                    675:                                case '4': case '5': case '6': case '7':
                    676:                                    c = *argp - '0';
                    677:                                    if(argp[1] <= '7' && argp[1] >= '0') {
                    678:                                        c <<= 3;
                    679:                                        c += *++argp - '0';
                    680:                                        if(argp[1] <= '7' && argp[1] >= '0') {
                    681:                                            c <<= 3;
                    682:                                            c += *++argp - '0';
                    683:                                        }
                    684:                                    }
                    685:                                    break;
                    686: #ifdef FKEYS
                    687:                                case 'f': case 'F':
                    688:                                    c = *++argp - '0';
                    689:                                    if(ISDIGIT(argp[1])) {
                    690:                                        c *= 10;
                    691:                                        c += *++argp - '0';
                    692:                                    }
                    693:                                    c += KFIRST;
                    694:                                    break;
                    695: #endif
                    696:                                default:
                    697:                                    c = CHARMASK(*argp);
                    698:                                    break;
                    699:                            }
                    700:                            argp++;
                    701:                        }
                    702: #ifdef FKEYS
                    703:                        if(bind == BINDARG)
                    704:                            key.k_chars[key.k_count++] = c;
                    705:                        else
                    706: #endif
                    707:                            lp->l_text[lp->l_used++] = c;
                    708:                    }
                    709:                    if(*line) line++;
                    710:                }
                    711: #ifdef FKEYS
                    712:                switch(bind) {
                    713:                    case BINDARG:
                    714:                        bind = BINDDO;
                    715:                        break;
                    716:                    case BINDNEXT:
                    717:                        lp->l_text[lp->l_used] = '\0';
                    718:                        if((mp = name_mode(lp->l_text)) == NULL) {
                    719:                            ewprintf("No such mode: %s", lp->l_text);
                    720:                            status = FALSE;
                    721:                            free((char *)lp);
                    722:                            goto cleanup;
                    723:                        }
                    724:                        curmap = mp->p_map;
                    725:                        free((char *)lp);
                    726:                        bind = BINDARG;
                    727:                        break;
                    728:                    default:
                    729: #endif
                    730:                        lp->l_fp = np->l_fp;
                    731:                        lp->l_bp = np;
                    732:                        np->l_fp = lp;
                    733:                        np = lp;
                    734: #ifdef FKEYS
                    735:                }
                    736: #endif
                    737:        }
                    738: #ifdef FKEYS
                    739:        switch(bind) {
                    740:            default:
                    741:                ewprintf("Bad args to set key");
                    742:                status = FALSE;
                    743:                break;
                    744:            case BINDDO:
                    745:                if(fp != unbindtokey && fp != localunbind) {
                    746:                    lp->l_text[lp->l_used] = '\0';
                    747:                    status = bindkey(&curmap, lp->l_text, key.k_chars, key.k_count);
                    748:                } else status = bindkey(&curmap, (char *)NULL, key.k_chars, key.k_count);
                    749:                break;
                    750:            case BINDNO:
                    751: #endif
                    752:                inmacro = TRUE;
                    753:                maclcur = maclcur->l_fp;
                    754:                status = (*fp)(f, n);
                    755:                inmacro = FALSE;
                    756: #ifdef FKEYS
                    757:        }
                    758: #endif
                    759: cleanup:
                    760:        lp = maclcur->l_fp;
                    761:        while(lp!=maclcur) {
                    762:            np = lp->l_fp;
                    763:            free((char *)lp);
                    764:            lp = np;
                    765:        }
                    766:        free((char *)lp);
                    767:        return status;
                    768: }
                    769:
                    770: /*
                    771:  * a pair of utility functions for the above
                    772:  */
                    773: static char *
                    774: skipwhite(s)
                    775: register char *s;
                    776: {
                    777:        while(*s == ' ' || *s == '\t' || *s == ')' || *s == '(') s++;
                    778:        if (*s == ';') *s = '\0' ;
                    779:        return s;
                    780: }
                    781:
                    782: static char *
                    783: parsetoken(s)
                    784: register char *s;
                    785: {
                    786:        if (*s != '"') {
                    787:            while(*s && *s!=' ' && *s!='\t' && *s!=')' && *s!='(') s++;
                    788:            if(*s==';') *s='\0';
                    789:        } else
                    790:            do {        /* Strings get special treatment */
                    791:                        /* Beware: You can \ out the end of the string! */
                    792:                if (*s == '\\') ++s;
                    793:            } while (*++s != '"' && *s != '\0');
                    794:        return s;
                    795: }
                    796: #endif