File: [local] / src / usr.bin / mg / extend.c (download)
Revision 1.53, Fri May 25 04:56:58 2012 UTC (12 years ago) by lum
Branch: MAIN
CVS Tags: OPENBSD_5_5_BASE, OPENBSD_5_5, OPENBSD_5_4_BASE, OPENBSD_5_4, OPENBSD_5_3_BASE, OPENBSD_5_3, OPENBSD_5_2_BASE, OPENBSD_5_2 Changes since 1.52: +6 -4 lines
Remove static FILE pointer used for handling files in fileio.c. Pass
by reference instead. This allows the mg startup file to open other
files without unexpected things happening.
Discussed with Sunil Nimmagadda.
|
/* $OpenBSD: extend.c,v 1.53 2012/05/25 04:56:58 lum Exp $ */
/* This file is in the public domain. */
/*
* Extended (M-X) commands, rebinding, and startup file processing.
*/
#include "chrdef.h"
#include "def.h"
#include "kbd.h"
#include "funmap.h"
#include <sys/types.h>
#include <ctype.h>
#include "macro.h"
#ifdef FKEYS
#include "key.h"
#ifndef BINDKEY
#define BINDKEY /* bindkey is used by FKEYS startup code */
#endif /* !BINDKEY */
#endif /* FKEYS */
#include <ctype.h>
static int remap(KEYMAP *, int, PF, KEYMAP *);
static KEYMAP *reallocmap(KEYMAP *);
static void fixmap(KEYMAP *, KEYMAP *, KEYMAP *);
static int dobind(KEYMAP *, const char *, int);
static char *skipwhite(char *);
static char *parsetoken(char *);
#ifdef BINDKEY
static int bindkey(KEYMAP **, const char *, KCHAR *, int);
#endif /* BINDKEY */
/*
* Insert a string, mainly for use from macros (created by selfinsert).
*/
/* ARGSUSED */
int
insert(int f, int n)
{
char buf[128], *bufp, *cp;
int count, c;
if (inmacro) {
while (--n >= 0) {
for (count = 0; count < maclcur->l_used; count++) {
if ((((c = maclcur->l_text[count]) == '\n')
? lnewline() : linsert(1, c)) != TRUE)
return (FALSE);
}
}
maclcur = maclcur->l_fp;
return (TRUE);
}
if (n == 1)
/* CFINS means selfinsert can tack on the end */
thisflag |= CFINS;
if ((bufp = eread("Insert: ", buf, sizeof(buf), EFNEW)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
while (--n >= 0) {
cp = buf;
while (*cp) {
if (((*cp == '\n') ? lnewline() : linsert(1, *cp))
!= TRUE)
return (FALSE);
cp++;
}
}
return (TRUE);
}
/*
* Bind a key to a function. Cases range from the trivial (replacing an
* existing binding) to the extremely complex (creating a new prefix in a
* map_element that already has one, so the map_element must be split,
* but the keymap doesn't have enough room for another map_element, so
* the keymap is reallocated). No attempt is made to reclaim space no
* longer used, if this is a problem flags must be added to indicate
* malloced versus static storage in both keymaps and map_elements.
* Structure assignments would come in real handy, but K&R based compilers
* don't have them. Care is taken so running out of memory will leave
* the keymap in a usable state.
* Parameters are:
* curmap: pointer to the map being changed
* c: character being changed
* funct: function being changed to
* pref_map: if funct==NULL, map to bind to or NULL for new
*/
static int
remap(KEYMAP *curmap, int c, PF funct, KEYMAP *pref_map)
{
int i, n1, n2, nold;
KEYMAP *mp, *newmap;
PF *pfp;
struct map_element *mep;
if (ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
if (ele > &curmap->map_element[0] && (funct != NULL ||
(ele - 1)->k_prefmap == NULL))
n1 = c - (ele - 1)->k_num;
else
n1 = HUGE;
if (ele < &curmap->map_element[curmap->map_num] &&
(funct != NULL || ele->k_prefmap == NULL))
n2 = ele->k_base - c;
else
n2 = HUGE;
if (n1 <= MAPELEDEF && n1 <= n2) {
ele--;
if ((pfp = calloc(c - ele->k_base + 1,
sizeof(PF))) == NULL) {
ewprintf("Out of memory");
return (FALSE);
}
nold = ele->k_num - ele->k_base + 1;
for (i = 0; i < nold; i++)
pfp[i] = ele->k_funcp[i];
while (--n1)
pfp[i++] = curmap->map_default;
pfp[i] = funct;
ele->k_num = c;
ele->k_funcp = pfp;
} else if (n2 <= MAPELEDEF) {
if ((pfp = calloc(ele->k_num - c + 1,
sizeof(PF))) == NULL) {
ewprintf("Out of memory");
return (FALSE);
}
nold = ele->k_num - ele->k_base + 1;
for (i = 0; i < nold; i++)
pfp[i + n2] = ele->k_funcp[i];
while (--n2)
pfp[n2] = curmap->map_default;
pfp[0] = funct;
ele->k_base = c;
ele->k_funcp = pfp;
} else {
if (curmap->map_num >= curmap->map_max) {
if ((newmap = reallocmap(curmap)) == NULL)
return (FALSE);
curmap = newmap;
}
if ((pfp = malloc(sizeof(PF))) == NULL) {
ewprintf("Out of memory");
return (FALSE);
}
pfp[0] = funct;
for (mep = &curmap->map_element[curmap->map_num];
mep > ele; mep--) {
mep->k_base = (mep - 1)->k_base;
mep->k_num = (mep - 1)->k_num;
mep->k_funcp = (mep - 1)->k_funcp;
mep->k_prefmap = (mep - 1)->k_prefmap;
}
ele->k_base = c;
ele->k_num = c;
ele->k_funcp = pfp;
ele->k_prefmap = NULL;
curmap->map_num++;
}
if (funct == NULL) {
if (pref_map != NULL)
ele->k_prefmap = pref_map;
else {
if ((mp = malloc(sizeof(KEYMAP) +
(MAPINIT - 1) * sizeof(struct map_element))) == NULL) {
ewprintf("Out of memory");
ele->k_funcp[c - ele->k_base] =
curmap->map_default;
return (FALSE);
}
mp->map_num = 0;
mp->map_max = MAPINIT;
mp->map_default = rescan;
ele->k_prefmap = mp;
}
}
} else {
n1 = c - ele->k_base;
if (ele->k_funcp[n1] == funct && (funct != NULL ||
pref_map == NULL || pref_map == ele->k_prefmap))
/* no change */
return (TRUE);
if (funct != NULL || ele->k_prefmap == NULL) {
if (ele->k_funcp[n1] == NULL)
ele->k_prefmap = NULL;
/* easy case */
ele->k_funcp[n1] = funct;
if (funct == NULL) {
if (pref_map != NULL)
ele->k_prefmap = pref_map;
else {
if ((mp = malloc(sizeof(KEYMAP) +
(MAPINIT - 1) *
sizeof(struct map_element))) == NULL) {
ewprintf("Out of memory");
ele->k_funcp[c - ele->k_base] =
curmap->map_default;
return (FALSE);
}
mp->map_num = 0;
mp->map_max = MAPINIT;
mp->map_default = rescan;
ele->k_prefmap = mp;
}
}
} else {
/*
* This case is the splits.
* Determine which side of the break c goes on
* 0 = after break; 1 = before break
*/
n2 = 1;
for (i = 0; n2 && i < n1; i++)
n2 &= ele->k_funcp[i] != NULL;
if (curmap->map_num >= curmap->map_max) {
if ((newmap = reallocmap(curmap)) == NULL)
return (FALSE);
curmap = newmap;
}
if ((pfp = calloc(ele->k_num - c + !n2,
sizeof(PF))) == NULL) {
ewprintf("Out of memory");
return (FALSE);
}
ele->k_funcp[n1] = NULL;
for (i = n1 + n2; i <= ele->k_num - ele->k_base; i++)
pfp[i - n1 - n2] = ele->k_funcp[i];
for (mep = &curmap->map_element[curmap->map_num];
mep > ele; mep--) {
mep->k_base = (mep - 1)->k_base;
mep->k_num = (mep - 1)->k_num;
mep->k_funcp = (mep - 1)->k_funcp;
mep->k_prefmap = (mep - 1)->k_prefmap;
}
ele->k_num = c - !n2;
(ele + 1)->k_base = c + n2;
(ele + 1)->k_funcp = pfp;
ele += !n2;
ele->k_prefmap = NULL;
curmap->map_num++;
if (pref_map == NULL) {
if ((mp = malloc(sizeof(KEYMAP) + (MAPINIT - 1)
* sizeof(struct map_element))) == NULL) {
ewprintf("Out of memory");
ele->k_funcp[c - ele->k_base] =
curmap->map_default;
return (FALSE);
}
mp->map_num = 0;
mp->map_max = MAPINIT;
mp->map_default = rescan;
ele->k_prefmap = mp;
} else
ele->k_prefmap = pref_map;
}
}
return (TRUE);
}
/*
* Reallocate a keymap. Returns NULL (without trashing the current map)
* on failure.
*/
static KEYMAP *
reallocmap(KEYMAP *curmap)
{
struct maps_s *mps;
KEYMAP *mp;
int i;
if (curmap->map_max > SHRT_MAX - MAPGROW) {
ewprintf("keymap too large");
return (NULL);
}
if ((mp = malloc(sizeof(KEYMAP) + (curmap->map_max + (MAPGROW - 1)) *
sizeof(struct map_element))) == NULL) {
ewprintf("Out of memory");
return (NULL);
}
mp->map_num = curmap->map_num;
mp->map_max = curmap->map_max + MAPGROW;
mp->map_default = curmap->map_default;
for (i = curmap->map_num; i--;) {
mp->map_element[i].k_base = curmap->map_element[i].k_base;
mp->map_element[i].k_num = curmap->map_element[i].k_num;
mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
}
for (mps = maps; mps != NULL; mps = mps->p_next) {
if (mps->p_map == curmap)
mps->p_map = mp;
else
fixmap(curmap, mp, mps->p_map);
}
ele = &mp->map_element[ele - &curmap->map_element[0]];
return (mp);
}
/*
* Fix references to a reallocated keymap (recursive).
*/
static void
fixmap(KEYMAP *curmap, KEYMAP *mp, KEYMAP *mt)
{
int i;
for (i = mt->map_num; i--;) {
if (mt->map_element[i].k_prefmap != NULL) {
if (mt->map_element[i].k_prefmap == curmap)
mt->map_element[i].k_prefmap = mp;
else
fixmap(curmap, mp, mt->map_element[i].k_prefmap);
}
}
}
/*
* Do the input for local-set-key, global-set-key and define-key
* then call remap to do the work.
*/
static int
dobind(KEYMAP *curmap, const char *p, int unbind)
{
KEYMAP *pref_map = NULL;
PF funct;
char bprompt[80], *bufp, *pep;
int c, s, n;
if (macrodef) {
/*
* Keystrokes aren't collected. Not hard, but pretty useless.
* Would not work for function keys in any case.
*/
ewprintf("Can't rebind key in macro");
return (FALSE);
}
if (inmacro) {
for (s = 0; s < maclcur->l_used - 1; s++) {
if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap)
!= NULL) {
if (remap(curmap, c, NULL, NULL)
!= TRUE)
return (FALSE);
}
}
(void)doscan(curmap, c = maclcur->l_text[s], NULL);
maclcur = maclcur->l_fp;
} else {
n = strlcpy(bprompt, p, sizeof(bprompt));
if (n >= sizeof(bprompt))
n = sizeof(bprompt) - 1;
pep = bprompt + n;
for (;;) {
ewprintf("%s", bprompt);
pep[-1] = ' ';
pep = getkeyname(pep, sizeof(bprompt) -
(pep - bprompt), c = getkey(FALSE));
if (doscan(curmap, c, &curmap) != NULL)
break;
*pep++ = '-';
*pep = '\0';
}
}
if (unbind)
funct = rescan;
else {
if ((bufp = eread("%s to command: ", bprompt, sizeof(bprompt),
EFFUNC | EFNEW, bprompt)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if (((funct = name_function(bprompt)) == NULL) ?
(pref_map = name_map(bprompt)) == NULL : funct == NULL) {
ewprintf("[No match]");
return (FALSE);
}
}
return (remap(curmap, c, funct, pref_map));
}
/*
* bindkey: bind key sequence to a function in the specified map. Used by
* excline so it can bind function keys. To close to release to change
* calling sequence, should just pass KEYMAP *curmap rather than
* KEYMAP **mapp.
*/
#ifdef BINDKEY
static int
bindkey(KEYMAP **mapp, const char *fname, KCHAR *keys, int kcount)
{
KEYMAP *curmap = *mapp;
KEYMAP *pref_map = NULL;
PF funct;
int c;
if (fname == NULL)
funct = rescan;
else if (((funct = name_function(fname)) == NULL) ?
(pref_map = name_map(fname)) == NULL : funct == NULL) {
ewprintf("[No match: %s]", fname);
return (FALSE);
}
while (--kcount) {
if (doscan(curmap, c = *keys++, &curmap) != NULL) {
if (remap(curmap, c, NULL, NULL) != TRUE)
return (FALSE);
/*
* XXX - Bizzarreness. remap creates an empty KEYMAP
* that the last key is supposed to point to.
*/
curmap = ele->k_prefmap;
}
}
(void)doscan(curmap, c = *keys, NULL);
return (remap(curmap, c, funct, pref_map));
}
#ifdef FKEYS
/*
* Wrapper for bindkey() that converts escapes.
*/
int
dobindkey(KEYMAP *map, const char *func, const char *str)
{
int i;
for (i = 0; *str && i < MAXKEY; i++) {
/* XXX - convert numbers w/ strol()? */
if (*str == '^' && *(str + 1) != '\0') {
key.k_chars[i] = CCHR(toupper(*++str));
} else if (*str == '\\' && *(str + 1) != '\0') {
switch (*++str) {
case '^':
key.k_chars[i] = '^';
break;
case 't':
case 'T':
key.k_chars[i] = '\t';
break;
case 'n':
case 'N':
key.k_chars[i] = '\n';
break;
case 'r':
case 'R':
key.k_chars[i] = '\r';
break;
case 'e':
case 'E':
key.k_chars[i] = CCHR('[');
break;
case '\\':
key.k_chars[i] = '\\';
break;
}
} else
key.k_chars[i] = *str;
str++;
}
key.k_count = i;
return (bindkey(&map, func, key.k_chars, key.k_count));
}
#endif /* FKEYS */
#endif /* BINDKEY */
/*
* This function modifies the fundamental keyboard map.
*/
/* ARGSUSED */
int
bindtokey(int f, int n)
{
return (dobind(fundamental_map, "Global set key: ", FALSE));
}
/*
* This function modifies the current mode's keyboard map.
*/
/* ARGSUSED */
int
localbind(int f, int n)
{
return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
"Local set key: ", FALSE));
}
/*
* This function redefines a key in any keymap.
*/
/* ARGSUSED */
int
redefine_key(int f, int n)
{
static char buf[48];
char tmp[32], *bufp;
KEYMAP *mp;
(void)strlcpy(buf, "Define key map: ", sizeof(buf));
if ((bufp = eread(buf, tmp, sizeof(tmp), EFNEW)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
(void)strlcat(buf, tmp, sizeof(buf));
if ((mp = name_map(tmp)) == NULL) {
ewprintf("Unknown map %s", tmp);
return (FALSE);
}
if (strlcat(buf, "key: ", sizeof(buf)) >= sizeof(buf))
return (FALSE);
return (dobind(mp, buf, FALSE));
}
/* ARGSUSED */
int
unbindtokey(int f, int n)
{
return (dobind(fundamental_map, "Global unset key: ", TRUE));
}
/* ARGSUSED */
int
localunbind(int f, int n)
{
return (dobind(curbp->b_modes[curbp->b_nmodes]->p_map,
"Local unset key: ", TRUE));
}
/*
* Extended command. Call the message line routine to read in the command
* name and apply autocompletion to it. When it comes back, look the name
* up in the symbol table and run the command if it is found. Print an
* error if there is anything wrong.
*/
int
extend(int f, int n)
{
PF funct;
char xname[NXNAME], *bufp;
if (!(f & FFARG))
bufp = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
else
bufp = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
if (bufp == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if ((funct = name_function(bufp)) != NULL) {
if (macrodef) {
struct line *lp = maclcur;
macro[macrocount - 1].m_funct = funct;
maclcur = lp->l_bp;
maclcur->l_fp = lp->l_fp;
free(lp);
}
return ((*funct)(f, n));
}
ewprintf("[No match]");
return (FALSE);
}
/*
* Define the commands needed to do startup-file processing.
* This code is mostly a kludge just so we can get startup-file processing.
*
* If you're serious about having this code, you should rewrite it.
* To wit:
* It has lots of funny things in it to make the startup-file look
* like a GNU startup file; mostly dealing with parens and semicolons.
* This should all vanish.
*
* We define eval-expression because it's easy. It can make
* *-set-key or define-key set an arbitrary key sequence, so it isn't
* useless.
*/
/*
* evalexpr - get one line from the user, and run it.
*/
/* ARGSUSED */
int
evalexpr(int f, int n)
{
char exbuf[128], *bufp;
if ((bufp = eread("Eval: ", exbuf, sizeof(exbuf),
EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
return (excline(exbuf));
}
/*
* evalbuffer - evaluate the current buffer as line commands. Useful for
* testing startup files.
*/
/* ARGSUSED */
int
evalbuffer(int f, int n)
{
struct line *lp;
struct buffer *bp = curbp;
int s;
static char excbuf[128];
for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) {
if (llength(lp) >= 128)
return (FALSE);
(void)strncpy(excbuf, ltext(lp), llength(lp));
/* make sure it's terminated */
excbuf[llength(lp)] = '\0';
if ((s = excline(excbuf)) != TRUE)
return (s);
}
return (TRUE);
}
/*
* evalfile - go get a file and evaluate it as line commands. You can
* go get your own startup file if need be.
*/
/* ARGSUSED */
int
evalfile(int f, int n)
{
char fname[NFILEN], *bufp;
if ((bufp = eread("Load file: ", fname, NFILEN,
EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
return (load(fname));
}
/*
* load - go load the file name we got passed.
*/
int
load(const char *fname)
{
int s = TRUE, line;
int nbytes = 0;
char excbuf[128];
FILE *ffp;
if ((fname = adjustname(fname, TRUE)) == NULL)
/* just to be careful */
return (FALSE);
if (ffropen(&ffp, fname, NULL) != FIOSUC)
return (FALSE);
line = 0;
while ((s = ffgetline(ffp, excbuf, sizeof(excbuf) - 1, &nbytes))
== FIOSUC) {
line++;
excbuf[nbytes] = '\0';
if (excline(excbuf) != TRUE) {
s = FIOERR;
ewprintf("Error loading file %s at line %d", fname, line);
break;
}
}
(void)ffclose(ffp, NULL);
excbuf[nbytes] = '\0';
if (s != FIOEOF || (nbytes && excline(excbuf) != TRUE))
return (FALSE);
return (TRUE);
}
/*
* excline - run a line from a load file or eval-expression. If FKEYS is
* defined, duplicate functionality of dobind so function key values don't
* have to fit in type char.
*/
int
excline(char *line)
{
PF fp;
struct line *lp, *np;
int status, c, f, n;
char *funcp, *tmp;
char *argp = NULL;
long nl;
#ifdef FKEYS
int bind;
KEYMAP *curmap;
#define BINDARG 0 /* this arg is key to bind (local/global set key) */
#define BINDNO 1 /* not binding or non-quoted BINDARG */
#define BINDNEXT 2 /* next arg " (define-key) */
#define BINDDO 3 /* already found key to bind */
#define BINDEXT 1 /* space for trailing \0 */
#else /* FKEYS */
#define BINDEXT 0
#endif /* FKEYS */
lp = NULL;
if (macrodef || inmacro) {
ewprintf("Not now!");
return (FALSE);
}
f = 0;
n = 1;
funcp = skipwhite(line);
if (*funcp == '\0')
return (TRUE); /* No error on blank lines */
line = parsetoken(funcp);
if (*line != '\0') {
*line++ = '\0';
line = skipwhite(line);
if (ISDIGIT(*line) || *line == '-') {
argp = line;
line = parsetoken(line);
}
}
if (argp != NULL) {
f = FFARG;
nl = strtol(argp, &tmp, 10);
if (*tmp != '\0')
return (FALSE);
if (nl >= INT_MAX || nl <= INT_MIN)
return (FALSE);
n = (int)nl;
}
if ((fp = name_function(funcp)) == NULL) {
ewprintf("Unknown function: %s", funcp);
return (FALSE);
}
#ifdef FKEYS
if (fp == bindtokey || fp == unbindtokey) {
bind = BINDARG;
curmap = fundamental_map;
} else if (fp == localbind || fp == localunbind) {
bind = BINDARG;
curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
} else if (fp == redefine_key)
bind = BINDNEXT;
else
bind = BINDNO;
#endif /* FKEYS */
/* Pack away all the args now... */
if ((np = lalloc(0)) == FALSE)
return (FALSE);
np->l_fp = np->l_bp = maclcur = np;
while (*line != '\0') {
argp = skipwhite(line);
if (*argp == '\0')
break;
line = parsetoken(argp);
if (*argp != '"') {
if (*argp == '\'')
++argp;
if ((lp = lalloc((int) (line - argp) + BINDEXT)) ==
NULL) {
status = FALSE;
goto cleanup;
}
bcopy(argp, ltext(lp), (int)(line - argp));
#ifdef FKEYS
/* don't count BINDEXT */
lp->l_used--;
if (bind == BINDARG)
bind = BINDNO;
#endif /* FKEYS */
} else {
/* quoted strings are special */
++argp;
#ifdef FKEYS
if (bind != BINDARG) {
#endif /* FKEYS */
lp = lalloc((int)(line - argp) + BINDEXT);
if (lp == NULL) {
status = FALSE;
goto cleanup;
}
lp->l_used = 0;
#ifdef FKEYS
} else
key.k_count = 0;
#endif /* FKEYS */
while (*argp != '"' && *argp != '\0') {
if (*argp != '\\')
c = *argp++;
else {
switch (*++argp) {
case 't':
case 'T':
c = CCHR('I');
break;
case 'n':
case 'N':
c = CCHR('J');
break;
case 'r':
case 'R':
c = CCHR('M');
break;
case 'e':
case 'E':
c = CCHR('[');
break;
case '^':
/*
* split into two statements
* due to bug in OSK cpp
*/
c = CHARMASK(*++argp);
c = ISLOWER(c) ?
CCHR(TOUPPER(c)) : CCHR(c);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
c = *argp - '0';
if (argp[1] <= '7' &&
argp[1] >= '0') {
c <<= 3;
c += *++argp - '0';
if (argp[1] <= '7' &&
argp[1] >= '0') {
c <<= 3;
c += *++argp
- '0';
}
}
break;
#ifdef FKEYS
case 'f':
case 'F':
c = *++argp - '0';
if (ISDIGIT(argp[1])) {
c *= 10;
c += *++argp - '0';
}
c += KFIRST;
break;
#endif /* FKEYS */
default:
c = CHARMASK(*argp);
break;
}
argp++;
}
#ifdef FKEYS
if (bind == BINDARG)
key.k_chars[key.k_count++] = c;
else
#endif /* FKEYS */
lp->l_text[lp->l_used++] = c;
}
if (*line)
line++;
}
#ifdef FKEYS
switch (bind) {
case BINDARG:
bind = BINDDO;
break;
case BINDNEXT:
lp->l_text[lp->l_used] = '\0';
if ((curmap = name_map(lp->l_text)) == NULL) {
ewprintf("No such mode: %s", lp->l_text);
status = FALSE;
free(lp);
goto cleanup;
}
free(lp);
bind = BINDARG;
break;
default:
#endif /* FKEYS */
lp->l_fp = np->l_fp;
lp->l_bp = np;
np->l_fp = lp;
np = lp;
#ifdef FKEYS
}
#endif /* FKEYS */
}
#ifdef FKEYS
switch (bind) {
default:
ewprintf("Bad args to set key");
status = FALSE;
break;
case BINDDO:
if (fp != unbindtokey && fp != localunbind) {
lp->l_text[lp->l_used] = '\0';
status = bindkey(&curmap, lp->l_text, key.k_chars,
key.k_count);
} else
status = bindkey(&curmap, NULL, key.k_chars,
key.k_count);
break;
case BINDNO:
#endif /* FKEYS */
inmacro = TRUE;
maclcur = maclcur->l_fp;
status = (*fp)(f, n);
inmacro = FALSE;
#ifdef FKEYS
}
#endif /* FKEYS */
cleanup:
lp = maclcur->l_fp;
while (lp != maclcur) {
np = lp->l_fp;
free(lp);
lp = np;
}
free(lp);
return (status);
}
/*
* a pair of utility functions for the above
*/
static char *
skipwhite(char *s)
{
while (*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
s++;
if (*s == ';')
*s = '\0';
return (s);
}
static char *
parsetoken(char *s)
{
if (*s != '"') {
while (*s && *s != ' ' && *s != '\t' && *s != ')' && *s != '(')
s++;
if (*s == ';')
*s = '\0';
} else
do {
/*
* Strings get special treatment.
* Beware: You can \ out the end of the string!
*/
if (*s == '\\')
++s;
} while (*++s != '"' && *s != '\0');
return (s);
}