home *** CD-ROM | disk | FTP | other *** search
- /*
- * Extended commands (M-X) and startup file processing.
- */
-
- #include "no_startup.h"
- #include "no_macro.h"
- #include "fkeys.h"
- #include "do_eval.h"
- #include "def.h"
-
- #ifndef NO_MACRO
- #include "macro.h"
- #endif
-
- #include "line.h"
- #include "buffer.h"
-
- #ifdef ANSI
- #include <stdlib.h>
- #include <string.h>
- #endif
-
- static char *skipwhite
- PROTO((char *s, char *end));
- static char *skiptowhite
- PROTO((char *s, char *end));
- static KCHAR backquote
- PROTO((char **inp));
-
- /*
- * 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.
- */
- extend(f, n)
- {
- int (*funct) PROTO((int, int));
- #ifndef NO_MACRO
- struct macro *m;
- #endif
- int s;
- char xname[NXNAME];
-
- if (!(f & FFARG))
- s = eread("M-x ", xname, NXNAME, EFNEW | EFFUNC);
- else
- s = eread("%d M-x ", xname, NXNAME, EFNEW | EFFUNC, n);
- if (s != TRUE)
- return s;
- if ((funct = name_function(xname)) != NULL)
- return (*funct) (f, n);
- #ifndef NO_MACRO
- else if ((m = find_macro(xname)) != NULL)
- return runmacro(m, f, n, FALSE);
- #endif
- ewprintf("[No match]");
- return FALSE;
- }
-
- #ifdef DO_EVAL
- /*
- * Define the commands needed to do startup-file processing. This code is
- * mostly a kludge just so we can get startup-file processing.
- *
- * 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 */
- evalexpr(f, n)
- {
- int s;
- char exbuf[NXNAME];
-
- if ((s = ereply("Eval: ", exbuf, NXNAME)) != TRUE)
- return s;
- return excline(exbuf, strlen(exbuf));
- }
- /*
- * evalbuffer - evaluate the current buffer as line commands. Useful for
- * testing startup files.
- */
- /* ARGSUSED */
- evalbuffer(f, n)
- {
- register struct line *lp;
- register struct buffer *bp = curbp;
- register int s;
-
- for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
- if (llength(lp) >= NLINE)
- return FALSE;
- if ((s = excline(ltext(lp), llength(lp))) != 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 */
- evalfile(f, n)
- {
- register int s;
- char fname[NFILEN];
-
- if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
- return s;
- return load(fname);
- }
-
- /*
- * load - go load the file name we got passed.
- */
- load(fname)
- char *fname;
- {
- int s = TRUE;
- int nbytes;
- char excbuf[128];
-
- if ((fname = adjustname(fname)) == NULL)
- return FALSE; /* just to be careful */
-
- if (ffropen(fname) != FIOSUC)
- return FALSE;
- while ((s = ffgetline(excbuf, sizeof(excbuf) - 1, &nbytes)) == FIOSUC) {
- if (excline(excbuf, nbytes) != TRUE) {
- s = FIOERR;
- ewprintf("Error loading file %s", fname);
- break;
- }
- }
- (VOID) ffclose();
- if (s != FIOEOF || (nbytes && excline(excbuf, nbytes) != TRUE))
- return FALSE;
- return TRUE;
- }
-
- /*
- * excline - run a line from a load file or eval-expression.
- */
- excline(line, len)
- char *line;
- int len;
- {
- /* end points to where the terminating null should be */
- char *funcp, *argp = NULL, *end, *inline;
- struct macro *eval;
- int status;
-
- /* Make a copy we can scrawl on */
- if (len == 0) return TRUE ;
- if ((inline = malloc(len + 1)) == NULL) return FALSE ;
- (VOID) bcopy(line, inline, len + 1);
- line = inline ;
-
- end = line + len; /* End of string marker */
- funcp = skipwhite(line, end);
- if (funcp >= end) {
- free(inline) ;
- return TRUE; /* No error on blank lines */
- }
- line = skiptowhite(funcp, end);
- *line++ = '\0';
- if (line < end) {
- argp = skipwhite(line, end);
- if (*argp != '-' && (*argp < '0' || '9' < *argp))
- argp = NULL;
- else {
- line = skiptowhite(argp, end);
- *line++ = '\0';
- }
- }
- if ((eval = (struct macro *) malloc(sizeof(struct macro))) == NULL) {
- free(inline) ;
- return FALSE;
- }
- eval->m_count = eval->m_max = 0;
- eval->m_text = eval->m_cur = NULL;
- if (argp != NULL) {
- add_key_to_macro(CCHR('U'), eval);
- add_string_to_macro(argp, eval);
- }
- add_key_to_macro(METACH, eval);
- add_key_to_macro('X', eval);
-
- /* Pack in function */
- add_string_to_macro(funcp, eval);
- add_key_to_macro(SOFTCR, eval);
-
- /* Pack away all the args now... */
- while (line < end) {
- argp = skipwhite(line, end);
- if (argp >= end)
- break;
-
- if (*argp != '"') {
- line = skiptowhite(argp, end);
- *line++ = '\0';
- add_string_to_macro(argp, eval);
- } else { /* Quoted strings special again */
- ++argp;
- while (*argp != '"' && argp < end) {
- if (*argp != '\\')
- add_key_to_macro((KCHAR) *argp++, eval);
- else
- add_key_to_macro(backquote(&argp), eval);
- }
- line = argp + 1;
- }
- add_key_to_macro(SOFTCR, eval);
- }
- status = runmacro(eval, FFOTHARG, 1, TRUE);
- free((char *) eval->m_text);
- free((char *) eval);
- free(inline) ;
- return status;
- }
- /*
- * a pair of utility functions for the above
- */
- static char *
- skipwhite(s, end)
- register char *s;
- register char *end;
- {
- while (*s == ' ' || *s == '\t' && s < end)
- s++;
- if (*s == ';')
- return end;
- return s;
- }
-
- static char *
- skiptowhite(s, end)
- register char *s;
- register char *end;
- {
- while (s < end && *s != ' ' && *s != '\t')
- s++;
- return s;
- }
-
- /*
- * Put a backquoted string element into the keyboard macro. Return pointer to
- * char following backquoted stuff.
- */
- static KCHAR
- backquote(inp)
- char **inp;
- {
- register char *in;
- register KCHAR c;
-
- in = *inp;
- in += 1; /* Skip over backquote */
- c = *in++;
- switch (ISUPPER(c) ? TOLOWER(c) : c) {
- case 't':
- c = CCHR('I');
- break;
- case 'n':
- c = CCHR('J');
- break;
- case 'r':
- c = CCHR('M');
- break;
- case '^':
- c = *in++;
- if (ISLOWER(c))
- c = TOUPPER(c);
- c = CCHR(c);
- break;
- case 'e':
- c = METACH;
- break;
- #ifdef FKEYS
- case 'f':
- c = 0;
- if (ISDIGIT(*in))
- c += *in++ - '0';
- if (ISDIGIT(*in))
- c = (10 * c) + *in++ - '0';
- if ((c += KFIRST) > KLAST)
- c = KLAST;
- break;
- #endif
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- c = *in - '0';
- if (in[1] <= '7' && in[1] >= '0') {
- c <<= 3;
- c += *++in - '0';
- if (in[1] <= '7' && in[1] >= '0') {
- c <<= 3;
- c += *++in - '0';
- }
- }
- break;
- default:
- c = CHARMASK(c);
- break;
- }
- *inp = in; /* put the pointer back */
- return c;
- }
- #endif
-