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