From 8555d07437e331b1e58ac839ce91d275a715263a Mon Sep 17 00:00:00 2001 From: Renaud Fivet Date: Sat, 11 Sep 2021 12:38:56 +0800 Subject: [PATCH] Revise command line parsing: making sure something; is token something followed by ; (a comment). --- eval.c | 111 +++++++++++++++++++++++++-------------------------------- exec.c | 102 ++++++++++++++++++++++++++-------------------------- 2 files changed, 99 insertions(+), 114 deletions(-) diff --git a/eval.c b/eval.c index 8c3dbe8..7412fd2 100644 --- a/eval.c +++ b/eval.c @@ -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 ; } /* diff --git a/exec.c b/exec.c index 8f61d62..b280528 100644 --- a/exec.c +++ b/exec.c @@ -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} {} * @@ -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 */