Revise command line parsing: making sure something; is token something followed by ; (a comment).

This commit is contained in:
Renaud 2021-09-11 12:38:56 +08:00
parent 78e296afbb
commit 8555d07437
2 changed files with 99 additions and 114 deletions

111
eval.c
View File

@ -44,7 +44,6 @@
#define TKSTR 9 /* quoted string literal */
#define TKCMD 10 /* command name */
static int gettyp( char *token) ;
/* Emacs global flag bit definitions (for gflags). */
/* if GFREAD is set, current buffer will be set on first file (read in) */
@ -1112,116 +1111,103 @@ static char *i_to_a( int i) {
return sp ;
}
/*
* find the type of a passed token
/* find the type of a token based on first character
*
* char *token; token to analyze
* char c ; first character of analyzed token
*/
static int gettyp( char *token) {
char c; /* first char in token */
/* grab the first char (this is all we need) */
c = *token;
switch (c) {
static int gettyp( char c) {
switch( c) {
case '*':
case ':':
return TKLBL ;
case 0: /* no blanks!!! */
return TKNUL ;
case '"':
return TKSTR;
return TKSTR ;
case '!':
return TKDIR;
return TKDIR ;
case '@':
return TKARG;
return TKARG ;
case '=':
return TKBUF;
return TKBUF ;
case '$':
return TKENV;
return TKENV ;
case '%':
return TKVAR;
return TKVAR ;
case '&':
return TKFUN;
case '*':
return TKLBL;
return TKFUN ;
default:
/* a numeric literal? */
if( (c >= '0' && c <= '9') || c == '-')
return TKLIT;
return TKLIT ;
else
return TKCMD;
return TKCMD ;
}
}
int is_it_cmd( char *token) {
return TKCMD == gettyp( token) ;
return TKCMD == gettyp( *token) ;
}
/*
* find the value of a token
/* find the value of a token
*
* char *token; token to evaluate
*/
const char *getval(char *token)
{
int status; /* error return */
struct buffer *bp; /* temp buffer pointer */
unsigned blen ; /* length of buffer argument */
int distmp; /* temporary discmd flag */
static char buf[NSTRING]; /* string buffer for some returns */
switch (gettyp(token)) {
case TKNUL:
return "";
const char *getval( char *token) {
static char buf[ NSTRING] ; /* string buffer for some returns */
switch( gettyp( *token)) {
case TKARG: /* interactive argument */
strcpy(token, getval(&token[1]));
distmp = discmd; /* echo it always! */
discmd = TRUE;
status = getstring( token, buf, NSTRING, nlc) ;
discmd = distmp;
strcpy( token, getval( &token[ 1])) ;
int distmp = discmd ; /* echo it always! */
discmd = TRUE ;
int status = getstring( token, buf, NSTRING, nlc) ;
discmd = distmp ;
if (status == ABORT)
return errorm;
return buf;
return errorm ;
return buf ;
case TKBUF: /* buffer contents fetch */
/* grab the right buffer */
strcpy(token, getval(&token[1]));
bp = bfind(token, FALSE, 0);
/* grab the right buffer */
strcpy( token, getval( &token[ 1])) ;
buffer_p bp = bfind( token, FALSE, 0) ;
if (bp == NULL)
return errorm;
return errorm ;
/* if the buffer is displayed, get the window
vars instead of the buffer vars */
/* if the buffer is displayed,
get the window vars instead of the buffer vars */
if (bp->b_nwnd > 0) {
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
}
/* make sure we are not at the end */
/* make sure we are not at the end */
if (bp->b_linep == bp->b_dotp)
return errorm;
/* grab the line as an argument */
blen = bp->b_dotp->l_used - bp->b_doto;
/* grab the line as an argument */
unsigned blen = bp->b_dotp->l_used - bp->b_doto;
if( blen >= sizeof buf)
blen = sizeof buf - 1 ;
mystrscpy( buf, bp->b_dotp->l_text + bp->b_doto, blen + 1) ;
/* and step the buffer's line ptr ahead a line */
/* and step the buffer's line ptr ahead a line */
bp->b_dotp = bp->b_dotp->l_fp;
bp->b_doto = 0;
/* if displayed buffer, reset window ptr vars */
/* if displayed buffer, reset window ptr vars */
if (bp->b_nwnd > 0) {
curwp->w_dotp = curbp->b_dotp;
curwp->w_doto = 0;
curwp->w_flag |= WFMOVE;
}
/* and return the spoils */
/* and return the spoils */
return buf;
case TKVAR:
@ -1230,18 +1216,19 @@ const char *getval(char *token)
return gtenv(token + 1);
case TKFUN:
return gtfun(token + 1);
case TKDIR:
return errorm;
case TKLBL:
return errorm;
case TKLIT:
return token;
case TKSTR:
return token + 1;
case TKCMD:
return token;
case TKDIR:
case TKLBL:
case TKNUL:
return "" ;
}
return errorm;
return errorm ;
}
/*

102
exec.c
View File

@ -102,36 +102,12 @@ BINDABLE( namedcmd) {
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
*/
BINDABLE( execcmd) {
char *cmdstr ; /* string holding command to execute */
/* get the line wanted */
int status = newmlarg( &cmdstr, "execute-command-line: ", 0) ;
if( status != TRUE)
return status ;
while( status == TRUE && n-- > 0)
status = docmd( cmdstr) ;
free( cmdstr) ;
return status ;
}
/* 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:
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} <command-name> {<argument string(s)>}
*
@ -139,6 +115,7 @@ BINDABLE( execcmd) {
*/
static int docmd( char *cline) {
char tkn[ NSTRING] ; /* next token off of command line */
int status ;
char *oldestr = execstr ; /* save last ptr to string to execute */
execstr = cline ; /* and set this one as current */
@ -149,27 +126,22 @@ static int docmd( char *cline) {
lastflag = thisflag ;
thisflag = 0 ;
int status = macarg( tkn, sizeof tkn) ;
if( status != TRUE) { /* and grab the first token */
execstr = oldestr;
return status;
}
for( ;;) {
/* evaluate next token */
status = macarg( tkn, sizeof tkn) ;
if( status != TRUE || !*tkn) {
execstr = oldestr ;
return status ;
}
/* process leadin argument */
if( !is_it_cmd( tkn)) {
f = TRUE;
/* macarg already includes a getval, skip for now
mystrscpy( tkn, getval( tkn), sizeof tkn) ;
*/
n = atoi(tkn);
/* proceed if it is a command */
if( is_it_cmd( tkn))
break ;
/* and now get the command to execute */
status = macarg( tkn, sizeof tkn) ;
if( status != TRUE) {
execstr = oldestr ;
return status ;
}
}
/* otherwise set as argument of coming command */
f = TRUE ;
n = atoi( tkn) ;
}
/* and match the token to see if it exists */
nbind_p nbp = fncmatch( tkn) ;
@ -195,6 +167,26 @@ 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
*/
BINDABLE( execcmd) {
char *cmdstr ; /* string holding command to execute */
/* get the line wanted */
int status = newmlarg( &cmdstr, "execute-command-line: ", 0) ;
if( status != TRUE)
return status ;
while( status == TRUE && n-- > 0)
status = docmd( cmdstr) ;
free( cmdstr) ;
return status ;
}
/* new token:
* chop a token off a string
* return a pointer past the token
@ -213,7 +205,8 @@ static char *newtoken( char *src, char **tokref) {
/* scan through the source string */
boolean quote_f = FALSE ; /* is the current string quoted? */
for( char c = *src ; c ; c = *++src) {
char c = *src ;
for( ; c ; c = *++src) {
/* process special characters */
if( c == '~') {
c = *++src ;
@ -238,12 +231,17 @@ static char *newtoken( char *src, char **tokref) {
break ;
}
} else {
/* check for the end of the token: end of string or space separator */
/* check for the end of the token: EOS, space or comment */
if( quote_f) {
if( c == '"')
break ;
} else if( c == ' ' || c == '\t')
break ;
else if( c == '#' || c == ';') {
/* comments act like EOS */
c = 0 ;
break ;
}
/* set quote mode if quote found */
if( c == '"')
@ -273,7 +271,7 @@ static char *newtoken( char *src, char **tokref) {
tok[ idx] = 0 ;
*tokref = tok ;
return src + (*src != 0) ;
return src + (c != 0) ;
}
static char *token( char *srcstr, char *tok, int maxtoksize) {
@ -607,7 +605,7 @@ static int dobuf( buffer_p bp) {
/* get procedure or macro name */
token( eline, &tkn[ 1], sizeof tkn - 1) ;
char c = tkn[ 1] ;
if( !c || c == '#' || c == ';') {
if( !c) {
/* no name */
storing_f = TRUE ; /* just throw away the lines (no bstore) */
} else if( c >= '1' && c <= '9') { /* number >= 1 */