/* 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 #include #include "buffer.h" #include "bind.h" #include "display.h" #include "estruct.h" #include "eval.h" #include "file.h" #include "flook.h" #include "input.h" #include "line.h" #include "random.h" #include "window.h" static char *execstr = NULL ; /* pointer to string to execute */ boolean clexec = FALSE ; /* command line execution flag */ /* Directive definitions */ #define DIF 0 #define DELSE 1 #define DENDIF 2 #define DGOTO 3 #define DRETURN 4 #define DENDM 5 #define DWHILE 6 #define DENDWHILE 7 #define DBREAK 8 #define DFORCE 9 #define NUMDIRS 10 /* The !WHILE directive in the execution language needs to * stack references to pending whiles. These are stored linked * to each currently open procedure via a linked list of * the following structure. */ struct while_block { struct line *w_begin; /* ptr to !while statement */ struct line *w_end; /* ptr to the !endwhile statement */ int w_type; /* block type */ struct while_block *w_next; /* next while */ }; #define BTWHILE 1 #define BTBREAK 2 /* 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" }; static char golabel[ NSTRING] = "" ; /* current line to go to */ static int execlevel = 0 ; /* execution IF level */ static struct buffer *bstore = NULL ; /* buffer to store macro text to */ static int mstore = FALSE ; /* storing text to macro flag */ static int dobuf( struct buffer *bp) ; static void freewhile( struct while_block *wp) ; void ue_system( const char *cmd) { int ret ; ret = system( cmd) ; if( ret == -1) { /* some actual handling needed here */ } } /* * 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); } static int docmd( char *cline) ; /* * 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 */ static 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 */ boolean 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; status = macarg( tkn, sizeof tkn) ; if( status != TRUE) { /* and grab the first token */ execstr = oldestr; return status; } /* process leadin argument */ if( !is_it_cmd( tkn)) { f = TRUE; strncpy( tkn, getval( tkn), sizeof tkn - 1) ; tkn[ sizeof tkn - 1] = '\0' ; n = atoi(tkn); /* and now get the command to execute */ status = macarg( tkn, sizeof tkn) ; if( status != 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 */ static 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; } void gettoken( char *tok, int maxtoksize) { execstr = token( execstr, tok, maxtoksize) ; } /* * get a macro line argument * * char *tok; buffer to place argument */ int macarg( char *tok, int toksz) { boolean savcle ; /* buffer to store original clexec */ int status; savcle = clexec; /* save execution mode */ clexec = TRUE; /* get the argument */ status = nextarg("", tok, toksz, 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) { char *tmpbuf ; /* if we are interactive, go get it! */ if (clexec == FALSE) return getstring(prompt, buffer, size, terminator); tmpbuf = malloc( size) ; /* grab token and advance past */ gettoken( tmpbuf, size) ; /* evaluate it */ strncpy( buffer, getval( tmpbuf), size - 1) ; buffer[ size - 1] = '\0' ; free( tmpbuf) ; 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 */ bname_t bname ; /* 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 */ bname_t bname ; /* 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], sizeof bname - 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 */ bname_t bufn ; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute buffer: ", bufn, sizeof bufn)) != 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