/* exec.c -- implements exec.h */ #include "exec.h" /* exec.c * * This file is for functions dealing with execution of * commands, command lines, buffers, files and startup files. * * written 1986 by Daniel Lawrence * modified by Petri Kutvonen */ #include #include "buffer.h" #include "bind.h" #include "display.h" #include "estruct.h" #include "edef.h" #include "eval.h" #include "file.h" #include "flook.h" #include "input.h" #include "line.h" /* directive name table: This holds the names of all the directives.... */ static const char *dname[] = { "if", "else", "endif", "goto", "return", "endm", "while", "endwhile", "break", "force" }; /* * Execute a named command even if it is not bound. */ int namedcmd(int f, int n) { fn_t kfunc; /* ptr to the requexted function to bind to */ /* prompt the user to type a named command */ mlwrite(": "); /* and now get the function name to execute */ kfunc = getname(); if (kfunc == NULL) { mlwrite("(No such function)"); return FALSE; } /* and then execute the command */ return kfunc(f, n); } /* * execcmd: * Execute a command line command to be typed in * by the user * * int f, n; default Flag and Numeric argument */ int execcmd(int f, int n) { int status; /* status return */ char cmdstr[NSTRING]; /* string holding command to execute */ /* get the line wanted */ if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE) return status; execlevel = 0; return docmd(cmdstr); } /* * docmd: * take a passed string as a command line and translate * it to be executed as a command. This function will be * used by execute-command-line and by all source and * startup files. Lastflag/thisflag is also updated. * * format of the command line is: * * {# arg} {} * * char *cline; command line to execute */ int docmd(char *cline) { int f; /* default argument flag */ int n; /* numeric repeat value */ fn_t fnc; /* function to execute */ int status; /* return status of function */ int oldcle; /* old contents of clexec flag */ char *oldestr; /* original exec string */ char tkn[NSTRING]; /* next token off of command line */ /* if we are scanning and not executing..go back here */ if (execlevel) return TRUE; oldestr = execstr; /* save last ptr to string to execute */ execstr = cline; /* and set this one as current */ /* first set up the default command values */ f = FALSE; n = 1; lastflag = thisflag; thisflag = 0; if ((status = macarg(tkn)) != TRUE) { /* and grab the first token */ execstr = oldestr; return status; } /* process leadin argument */ if (gettyp(tkn) != TKCMD) { f = TRUE; strcpy(tkn, getval(tkn)); n = atoi(tkn); /* and now get the command to execute */ if ((status = macarg(tkn)) != TRUE) { execstr = oldestr; return status; } } /* and match the token to see if it exists */ if ((fnc = fncmatch(tkn)) == NULL) { mlwrite("(No such Function)"); execstr = oldestr; return FALSE; } /* save the arguments and go execute the command */ oldcle = clexec; /* save old clexec flag */ clexec = TRUE; /* in cline execution */ status = (*fnc) (f, n); /* call the function */ cmdstatus = status; /* save the status */ clexec = oldcle; /* restore clexec flag */ execstr = oldestr; return status; } /* * token: * chop a token off a string * return a pointer past the token * * char *src, *tok; source string, destination token string * int size; maximum size of token */ char *token(char *src, char *tok, int size) { int quotef; /* is the current string quoted? */ char c; /* temporary character */ /* first scan past any whitespace in the source string */ while (*src == ' ' || *src == '\t') ++src; /* scan through the source string */ quotef = FALSE; while (*src) { /* process special characters */ if (*src == '~') { ++src; if (*src == 0) break; switch (*src++) { case 'r': c = 13; break; case 'n': c = 10; break; case 't': c = 9; break; case 'b': c = 8; break; case 'f': c = 12; break; default: c = *(src - 1); } if (--size > 0) { *tok++ = c; } } else { /* check for the end of the token */ if (quotef) { if (*src == '"') break; } else { if (*src == ' ' || *src == '\t') break; } /* set quote mode if quote found */ if (*src == '"') quotef = TRUE; /* record the character */ c = *src++; if (--size > 0) *tok++ = c; } } /* terminate the token and exit */ if (*src) ++src; *tok = 0; return src; } /* * get a macro line argument * * char *tok; buffer to place argument */ int macarg(char *tok) { int savcle; /* buffer to store original clexec */ int status; savcle = clexec; /* save execution mode */ clexec = TRUE; /* get the argument */ status = nextarg("", tok, NSTRING, ctoec('\n')); clexec = savcle; /* restore execution mode */ return status; } /* * nextarg: * get the next argument * * const char *prompt; prompt to use if we must be interactive * char *buffer; buffer to put token into * int size; size of the buffer * int terminator; terminating char to be used on interactive fetch */ int nextarg(const char *prompt, char *buffer, int size, int terminator) { /* if we are interactive, go get it! */ if (clexec == FALSE) return getstring(prompt, buffer, size, terminator); /* grab token and advance past */ execstr = token(execstr, buffer, size); /* evaluate it */ strcpy(buffer, getval(buffer)); return TRUE; } /* * storemac: * Set up a macro buffer and flag to store all * executed command lines there * * int f; default flag * int n; macro number to use */ int storemac(int f, int n) { struct buffer *bp; /* pointer to macro buffer */ char bname[NBUFN]; /* name of buffer to use */ /* must have a numeric argument to this function */ if (f == FALSE) { mlwrite("No macro specified"); return FALSE; } /* range check the macro number */ if (n < 1 || n > 40) { mlwrite("Macro number out of range"); return FALSE; } /* construct the macro buffer name */ strcpy(bname, "*Macro xx*"); bname[7] = '0' + (n / 10); bname[8] = '0' + (n % 10); /* set up the new macro buffer */ if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { mlwrite("Can not create macro"); return FALSE; } /* and make sure it is empty */ bclear(bp); /* and set the macro store pointers to it */ mstore = TRUE; bstore = bp; return TRUE; } #if PROC /* * storeproc: * Set up a procedure buffer and flag to store all * executed command lines there * * int f; default flag * int n; macro number to use */ int storeproc(int f, int n) { struct buffer *bp; /* pointer to macro buffer */ int status; /* return status */ char bname[NBUFN]; /* name of buffer to use */ /* a numeric argument means its a numbered macro */ if (f == TRUE) return storemac(f, n); /* get the name of the procedure */ if ((status = mlreply("Procedure name: ", &bname[1], NBUFN - 2)) != TRUE) return status; /* construct the macro buffer name */ bname[0] = '*'; strcat(bname, "*"); /* set up the new macro buffer */ if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) { mlwrite("Can not create macro"); return FALSE; } /* and make sure it is empty */ bclear(bp); /* and set the macro store pointers to it */ mstore = TRUE; bstore = bp; return TRUE; } /* * execproc: * Execute a procedure * * int f, n; default flag and numeric arg */ int execproc(int f, int n) { struct buffer *bp; /* ptr to buffer to execute */ int status; /* status return */ char bufn[NBUFN + 2]; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute procedure: ", &bufn[1], NBUFN)) != TRUE) return status; /* construct the buffer name */ bufn[0] = '*'; strcat(bufn, "*"); /* find the pointer to that buffer */ if ((bp = bfind(bufn, FALSE, 0)) == NULL) { mlwrite("No such procedure"); return FALSE; } /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return status; return TRUE; } #endif /* * execbuf: * Execute the contents of a buffer of commands * * int f, n; default flag and numeric arg */ int execbuf(int f, int n) { struct buffer *bp; /* ptr to buffer to execute */ int status; /* status return */ char bufn[NSTRING]; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) return status; /* find the pointer to that buffer */ if ((bp = bfind(bufn, FALSE, 0)) == NULL) { mlwrite("No such buffer"); return FALSE; } /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return status; return TRUE; } /* * dobuf: * execute the contents of the buffer pointed to * by the passed BP * * Directives start with a "!" and include: * * !endm End a macro * !if (cond) conditional execution * !else * !endif * !return Return (terminating current macro) * !goto