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 TKSTR 9 /* quoted string literal */
#define TKCMD 10 /* command name */ #define TKCMD 10 /* command name */
static int gettyp( char *token) ;
/* Emacs global flag bit definitions (for gflags). */ /* Emacs global flag bit definitions (for gflags). */
/* if GFREAD is set, current buffer will be set on first file (read in) */ /* 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 ; 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) { static int gettyp( char c) {
char c; /* first char in token */ switch( c) {
case '*':
/* grab the first char (this is all we need) */ case ':':
c = *token; return TKLBL ;
switch (c) {
case 0: /* no blanks!!! */ case 0: /* no blanks!!! */
return TKNUL ; return TKNUL ;
case '"': case '"':
return TKSTR; return TKSTR ;
case '!': case '!':
return TKDIR; return TKDIR ;
case '@': case '@':
return TKARG; return TKARG ;
case '=': case '=':
return TKBUF; return TKBUF ;
case '$': case '$':
return TKENV; return TKENV ;
case '%': case '%':
return TKVAR; return TKVAR ;
case '&': case '&':
return TKFUN; return TKFUN ;
case '*':
return TKLBL;
default: default:
/* a numeric literal? */ /* a numeric literal? */
if( (c >= '0' && c <= '9') || c == '-') if( (c >= '0' && c <= '9') || c == '-')
return TKLIT; return TKLIT ;
else else
return TKCMD; return TKCMD ;
} }
} }
int is_it_cmd( char *token) { 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 * char *token; token to evaluate
*/ */
const char *getval(char *token) const char *getval( char *token) {
{ static char buf[ NSTRING] ; /* string buffer for some returns */
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 "";
switch( gettyp( *token)) {
case TKARG: /* interactive argument */ case TKARG: /* interactive argument */
strcpy(token, getval(&token[1])); strcpy( token, getval( &token[ 1])) ;
distmp = discmd; /* echo it always! */ int distmp = discmd ; /* echo it always! */
discmd = TRUE; discmd = TRUE ;
status = getstring( token, buf, NSTRING, nlc) ; int status = getstring( token, buf, NSTRING, nlc) ;
discmd = distmp; discmd = distmp ;
if (status == ABORT) if (status == ABORT)
return errorm; return errorm ;
return buf;
return buf ;
case TKBUF: /* buffer contents fetch */ case TKBUF: /* buffer contents fetch */
/* grab the right buffer */
/* grab the right buffer */ strcpy( token, getval( &token[ 1])) ;
strcpy(token, getval(&token[1])); buffer_p bp = bfind( token, FALSE, 0) ;
bp = bfind(token, FALSE, 0);
if (bp == NULL) if (bp == NULL)
return errorm; return errorm ;
/* if the buffer is displayed, get the window /* if the buffer is displayed,
vars instead of the buffer vars */ get the window vars instead of the buffer vars */
if (bp->b_nwnd > 0) { if (bp->b_nwnd > 0) {
curbp->b_dotp = curwp->w_dotp; curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto; 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) if (bp->b_linep == bp->b_dotp)
return errorm; return errorm;
/* grab the line as an argument */ /* grab the line as an argument */
blen = bp->b_dotp->l_used - bp->b_doto; unsigned blen = bp->b_dotp->l_used - bp->b_doto;
if( blen >= sizeof buf) if( blen >= sizeof buf)
blen = sizeof buf - 1 ; blen = sizeof buf - 1 ;
mystrscpy( buf, bp->b_dotp->l_text + bp->b_doto, blen + 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_dotp = bp->b_dotp->l_fp;
bp->b_doto = 0; bp->b_doto = 0;
/* if displayed buffer, reset window ptr vars */ /* if displayed buffer, reset window ptr vars */
if (bp->b_nwnd > 0) { if (bp->b_nwnd > 0) {
curwp->w_dotp = curbp->b_dotp; curwp->w_dotp = curbp->b_dotp;
curwp->w_doto = 0; curwp->w_doto = 0;
curwp->w_flag |= WFMOVE; curwp->w_flag |= WFMOVE;
} }
/* and return the spoils */ /* and return the spoils */
return buf; return buf;
case TKVAR: case TKVAR:
@ -1230,18 +1216,19 @@ const char *getval(char *token)
return gtenv(token + 1); return gtenv(token + 1);
case TKFUN: case TKFUN:
return gtfun(token + 1); return gtfun(token + 1);
case TKDIR:
return errorm;
case TKLBL:
return errorm;
case TKLIT: case TKLIT:
return token; return token;
case TKSTR: case TKSTR:
return token + 1; return token + 1;
case TKCMD: case TKCMD:
return token; 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) ; 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: /* docmd:
* take a passed string as a command line and translate take a passed string as a command line and translate it to be executed
* it to be executed as a command. This function will be as a command. This function will be used by execute-command-line and by
* used by execute-command-line and by all source and all source and startup files. Lastflag/thisflag is also updated.
* startup files. Lastflag/thisflag is also updated.
* * format of the command line is:
* format of the command line is:
* *
* {# arg} <command-name> {<argument string(s)>} * {# arg} <command-name> {<argument string(s)>}
* *
@ -139,6 +115,7 @@ BINDABLE( execcmd) {
*/ */
static int docmd( char *cline) { static int docmd( char *cline) {
char tkn[ NSTRING] ; /* next token off of command line */ char tkn[ NSTRING] ; /* next token off of command line */
int status ;
char *oldestr = execstr ; /* save last ptr to string to execute */ char *oldestr = execstr ; /* save last ptr to string to execute */
execstr = cline ; /* and set this one as current */ execstr = cline ; /* and set this one as current */
@ -149,27 +126,22 @@ static int docmd( char *cline) {
lastflag = thisflag ; lastflag = thisflag ;
thisflag = 0 ; thisflag = 0 ;
int status = macarg( tkn, sizeof tkn) ; for( ;;) {
if( status != TRUE) { /* and grab the first token */ /* evaluate next token */
execstr = oldestr; status = macarg( tkn, sizeof tkn) ;
return status; if( status != TRUE || !*tkn) {
} execstr = oldestr ;
return status ;
}
/* process leadin argument */ /* proceed if it is a command */
if( !is_it_cmd( tkn)) { if( is_it_cmd( tkn))
f = TRUE; break ;
/* macarg already includes a getval, skip for now
mystrscpy( tkn, getval( tkn), sizeof tkn) ;
*/
n = atoi(tkn);
/* and now get the command to execute */ /* otherwise set as argument of coming command */
status = macarg( tkn, sizeof tkn) ; f = TRUE ;
if( status != TRUE) { n = atoi( tkn) ;
execstr = oldestr ; }
return status ;
}
}
/* and match the token to see if it exists */ /* and match the token to see if it exists */
nbind_p nbp = fncmatch( tkn) ; 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: /* new token:
* chop a token off a string * chop a token off a string
* return a pointer past the token * return a pointer past the token
@ -213,7 +205,8 @@ static char *newtoken( char *src, char **tokref) {
/* scan through the source string */ /* scan through the source string */
boolean quote_f = FALSE ; /* is the current string quoted? */ 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 */ /* process special characters */
if( c == '~') { if( c == '~') {
c = *++src ; c = *++src ;
@ -238,12 +231,17 @@ static char *newtoken( char *src, char **tokref) {
break ; break ;
} }
} else { } 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( quote_f) {
if( c == '"') if( c == '"')
break ; break ;
} else if( c == ' ' || c == '\t') } else if( c == ' ' || c == '\t')
break ; break ;
else if( c == '#' || c == ';') {
/* comments act like EOS */
c = 0 ;
break ;
}
/* set quote mode if quote found */ /* set quote mode if quote found */
if( c == '"') if( c == '"')
@ -273,7 +271,7 @@ static char *newtoken( char *src, char **tokref) {
tok[ idx] = 0 ; tok[ idx] = 0 ;
*tokref = tok ; *tokref = tok ;
return src + (*src != 0) ; return src + (c != 0) ;
} }
static char *token( char *srcstr, char *tok, int maxtoksize) { static char *token( char *srcstr, char *tok, int maxtoksize) {
@ -607,7 +605,7 @@ static int dobuf( buffer_p bp) {
/* get procedure or macro name */ /* get procedure or macro name */
token( eline, &tkn[ 1], sizeof tkn - 1) ; token( eline, &tkn[ 1], sizeof tkn - 1) ;
char c = tkn[ 1] ; char c = tkn[ 1] ;
if( !c || c == '#' || c == ';') { if( !c) {
/* no name */ /* no name */
storing_f = TRUE ; /* just throw away the lines (no bstore) */ storing_f = TRUE ; /* just throw away the lines (no bstore) */
} else if( c >= '1' && c <= '9') { /* number >= 1 */ } else if( c >= '1' && c <= '9') { /* number >= 1 */