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