mirror of
https://github.com/rfivet/uemacs.git
synced 2024-06-10 05:50:42 +00:00
!gosub
Use generic list deletion API. Remove lines at parsing time.
This commit is contained in:
parent
2674d40d4c
commit
296f0af96c
126
exec.c
126
exec.c
|
@ -19,6 +19,7 @@
|
||||||
#include "flook.h"
|
#include "flook.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "line.h"
|
#include "line.h"
|
||||||
|
#include "list.h"
|
||||||
#include "mlout.h"
|
#include "mlout.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -39,18 +40,24 @@ boolean clexec = FALSE ; /* command line execution flag */
|
||||||
#define DENDWHILE 7
|
#define DENDWHILE 7
|
||||||
#define DBREAK 8
|
#define DBREAK 8
|
||||||
#define DFORCE 9
|
#define DFORCE 9
|
||||||
|
#define DGOSUB 10
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct caller {
|
||||||
|
struct caller *next ;
|
||||||
|
line_p caller ;
|
||||||
|
} *caller_p ;
|
||||||
|
|
||||||
/* The !WHILE directive in the execution language needs to
|
/* The !WHILE directive in the execution language needs to
|
||||||
* stack references to pending whiles. These are stored linked
|
* stack references to pending whiles. These are stored linked
|
||||||
* to each currently open procedure via a linked list of
|
* to each currently open procedure via a linked list of
|
||||||
* the following structure.
|
* the following structure.
|
||||||
*/
|
*/
|
||||||
typedef struct while_block {
|
typedef struct while_block {
|
||||||
|
struct while_block *w_next ; /* next while */
|
||||||
line_p w_begin ; /* ptr to !while statement */
|
line_p w_begin ; /* ptr to !while statement */
|
||||||
line_p w_end ; /* ptr to the !endwhile statement */
|
line_p w_end ; /* ptr to the !endwhile statement */
|
||||||
int w_type ; /* block type */
|
int w_type ; /* block type */
|
||||||
struct while_block *w_next ; /* next while */
|
|
||||||
} *while_p ;
|
} *while_p ;
|
||||||
|
|
||||||
#define BTWHILE 1
|
#define BTWHILE 1
|
||||||
|
@ -60,7 +67,8 @@ typedef struct while_block {
|
||||||
|
|
||||||
static const char *dname[] = {
|
static const char *dname[] = {
|
||||||
"if", "else", "endif", "goto", "return",
|
"if", "else", "endif", "goto", "return",
|
||||||
"endm", "while", "endwhile", "break", "force"
|
"endm", "while", "endwhile", "break", "force",
|
||||||
|
"gosub"
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
#define NUMDIRS ARRAY_SIZE( dname)
|
#define NUMDIRS ARRAY_SIZE( dname)
|
||||||
|
@ -185,8 +193,8 @@ static int docmd( char *cline) {
|
||||||
return status ;
|
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
|
||||||
*
|
*
|
||||||
|
@ -203,16 +211,15 @@ static char *newtoken( char *src, char **tokref) {
|
||||||
++src ;
|
++src ;
|
||||||
|
|
||||||
/* scan through the source string */
|
/* scan through the source string */
|
||||||
boolean quotef = FALSE ; /* is the current string quoted? */
|
boolean quote_f = FALSE ; /* is the current string quoted? */
|
||||||
while( *src) {
|
for( char c = *src ; c ; c = *++src) {
|
||||||
char c ; /* temporary character */
|
|
||||||
|
|
||||||
/* process special characters */
|
/* process special characters */
|
||||||
if( *src == '~') {
|
if( c == '~') {
|
||||||
++src;
|
c = *++src ;
|
||||||
if (*src == 0)
|
if( c == 0)
|
||||||
break ;
|
break ;
|
||||||
switch (*src++) {
|
|
||||||
|
switch( c) {
|
||||||
case 'r':
|
case 'r':
|
||||||
c = 13 ;
|
c = 13 ;
|
||||||
break ;
|
break ;
|
||||||
|
@ -228,27 +235,21 @@ static char *newtoken( char *src, char **tokref) {
|
||||||
case 'f':
|
case 'f':
|
||||||
c = 12 ;
|
c = 12 ;
|
||||||
break ;
|
break ;
|
||||||
default:
|
|
||||||
c = *(src - 1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* check for the end of the token */
|
/* check for the end of the token: end of string or space separator */
|
||||||
if (quotef) {
|
if( quote_f) {
|
||||||
if (*src == '"')
|
if( c == '"')
|
||||||
break ;
|
break ;
|
||||||
} else {
|
} else if( c == ' ' || c == '\t')
|
||||||
if (*src == ' ' || *src == '\t')
|
|
||||||
break ;
|
break ;
|
||||||
}
|
|
||||||
|
|
||||||
/* set quote mode if quote found */
|
/* set quote mode if quote found */
|
||||||
if (*src == '"')
|
if( c == '"')
|
||||||
quotef = TRUE;
|
quote_f = TRUE ;
|
||||||
|
|
||||||
/* record the character */
|
|
||||||
c = *src++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* record the character */
|
||||||
if( idx < size - 1)
|
if( idx < size - 1)
|
||||||
tok[ idx++] = c ;
|
tok[ idx++] = c ;
|
||||||
else if( size > 1) {
|
else if( size > 1) {
|
||||||
|
@ -256,7 +257,7 @@ static char *newtoken( char *src, char **tokref) {
|
||||||
|
|
||||||
tmptok = malloc( size + 32) ;
|
tmptok = malloc( size + 32) ;
|
||||||
if( tmptok == NULL)
|
if( tmptok == NULL)
|
||||||
size = 0 ;
|
size = 0 ; /* can't store more */
|
||||||
else {
|
else {
|
||||||
memcpy( tmptok, tok, idx) ;
|
memcpy( tmptok, tok, idx) ;
|
||||||
free( tok) ;
|
free( tok) ;
|
||||||
|
@ -267,15 +268,11 @@ static char *newtoken( char *src, char **tokref) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate the token and exit */
|
|
||||||
if (*src)
|
|
||||||
++src;
|
|
||||||
|
|
||||||
if( tok != NULL)
|
if( tok != NULL)
|
||||||
tok[ idx] = 0 ;
|
tok[ idx] = 0 ;
|
||||||
|
|
||||||
*tokref = tok ;
|
*tokref = tok ;
|
||||||
return src;
|
return src + (*src != 0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *token( char *srcstr, char *tok, int maxtoksize) {
|
static char *token( char *srcstr, char *tok, int maxtoksize) {
|
||||||
|
@ -488,19 +485,6 @@ BINDABLE( execbuf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* free a list of while block pointers
|
|
||||||
*
|
|
||||||
* while_p wp; head of structure to free
|
|
||||||
*/
|
|
||||||
static void freewhile( while_p wp) {
|
|
||||||
while( wp != NULL) {
|
|
||||||
while_p next = wp->w_next ;
|
|
||||||
free( wp) ;
|
|
||||||
wp = next ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static boolean storeline( char *eline, int linlen) {
|
static boolean storeline( char *eline, int linlen) {
|
||||||
/* allocate the space for the line */
|
/* allocate the space for the line */
|
||||||
line_p mp = lalloc( linlen) ;
|
line_p mp = lalloc( linlen) ;
|
||||||
|
@ -564,19 +548,10 @@ static int dobuf( buffer_p bp) {
|
||||||
if( *eline != ' ' && *eline != '\t')
|
if( *eline != ' ' && *eline != '\t')
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
/* empty blank and comment lines */
|
/* delete blank and comment lines */
|
||||||
if( eline == eol || *eline == '#' || *eline == ';') {
|
if( eline == eol || *eline == '#' || *eline == ';') {
|
||||||
if( bp->b_nwnd != 0)
|
|
||||||
lp->l_used = 0 ;
|
|
||||||
else {
|
|
||||||
/* delete line if buffer is not displayed */
|
|
||||||
line_p curlp = lp ;
|
|
||||||
lp = lp->l_bp ;
|
lp = lp->l_bp ;
|
||||||
lp->l_fp = curlp->l_fp ;
|
lfree( lp->l_fp) ;
|
||||||
curlp->l_fp->l_bp = lp ;
|
|
||||||
free( curlp) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue ;
|
continue ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +573,9 @@ static int dobuf( buffer_p bp) {
|
||||||
} else if( !storeline( lp->l_text, lp->l_used))
|
} else if( !storeline( lp->l_text, lp->l_used))
|
||||||
goto failexit ;
|
goto failexit ;
|
||||||
|
|
||||||
lp->l_used = 0 ;
|
/* remove line */
|
||||||
|
lp = lp->l_bp ;
|
||||||
|
lfree( lp->l_fp) ;
|
||||||
continue ;
|
continue ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,8 +595,7 @@ static int dobuf( buffer_p bp) {
|
||||||
if( !strncmp( eline, "!store", 6)) {
|
if( !strncmp( eline, "!store", 6)) {
|
||||||
if( lp->l_used < lp->l_size) {
|
if( lp->l_used < lp->l_size) {
|
||||||
eline[ lp->l_used] = 0 ;
|
eline[ lp->l_used] = 0 ;
|
||||||
execstr = &eline[ 6] ;
|
token( &eline[ 6], &tkn[ 1], sizeof tkn - 1) ;
|
||||||
gettoken( &tkn[ 1], sizeof tkn - 1) ;
|
|
||||||
char c = tkn[ 1] ;
|
char c = tkn[ 1] ;
|
||||||
if( c >= '1' && c <= '9') { /* number >= 1 */
|
if( c >= '1' && c <= '9') { /* number >= 1 */
|
||||||
if( !storemac( TRUE, atoi( &tkn[ 1])))
|
if( !storemac( TRUE, atoi( &tkn[ 1])))
|
||||||
|
@ -632,7 +608,9 @@ static int dobuf( buffer_p bp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->l_used = 0 ;
|
/* remove line */
|
||||||
|
lp = lp->l_bp ;
|
||||||
|
lfree( lp->l_fp) ;
|
||||||
continue ;
|
continue ;
|
||||||
} else if( !strncmp( eline, "!while", 6)) {
|
} else if( !strncmp( eline, "!while", 6)) {
|
||||||
/* if it is a while directive, make a block... */
|
/* if it is a while directive, make a block... */
|
||||||
|
@ -693,8 +671,8 @@ static int dobuf( buffer_p bp) {
|
||||||
/* while and endwhile should match! */
|
/* while and endwhile should match! */
|
||||||
mloutfmt( "%%!WHILE with no matching !ENDWHILE in '%s'", bp->b_bname) ;
|
mloutfmt( "%%!WHILE with no matching !ENDWHILE in '%s'", bp->b_bname) ;
|
||||||
failexit:
|
failexit:
|
||||||
freewhile( scanner) ;
|
freelist( (list_p) scanner) ;
|
||||||
freewhile( whlist) ;
|
freelist( (list_p) whlist) ;
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,6 +685,7 @@ static int dobuf( buffer_p bp) {
|
||||||
int status = TRUE ; /* status of command execution */
|
int status = TRUE ; /* status of command execution */
|
||||||
boolean done = FALSE ;
|
boolean done = FALSE ;
|
||||||
int execlevel = 0 ; /* execution IF level */
|
int execlevel = 0 ; /* execution IF level */
|
||||||
|
caller_p returnto = NULL ;
|
||||||
line_p lp = hlp->l_fp ;
|
line_p lp = hlp->l_fp ;
|
||||||
for( ; lp != hlp ; lp = lp->l_fp) {
|
for( ; lp != hlp ; lp = lp->l_fp) {
|
||||||
if( einit) {
|
if( einit) {
|
||||||
|
@ -850,6 +829,7 @@ static int dobuf( buffer_p bp) {
|
||||||
--execlevel ;
|
--execlevel ;
|
||||||
|
|
||||||
break ;
|
break ;
|
||||||
|
case DGOSUB: /* GOSUB directive */
|
||||||
case DGOTO: /* GOTO directive */
|
case DGOTO: /* GOTO directive */
|
||||||
/* .....only if we are currently executing */
|
/* .....only if we are currently executing */
|
||||||
if( execlevel != 0)
|
if( execlevel != 0)
|
||||||
|
@ -865,6 +845,18 @@ static int dobuf( buffer_p bp) {
|
||||||
char c = *glp->l_text ;
|
char c = *glp->l_text ;
|
||||||
if( (c == '*' || c == ':')
|
if( (c == '*' || c == ':')
|
||||||
&& !strncmp( &glp->l_text[ 1], golabel, linlen)) {
|
&& !strncmp( &glp->l_text[ 1], golabel, linlen)) {
|
||||||
|
if( dirnum == DGOSUB) {
|
||||||
|
caller_p cp = malloc( sizeof *cp) ;
|
||||||
|
if( cp == NULL) {
|
||||||
|
status = mloutfail( "OoM on !gosub") ;
|
||||||
|
break ;
|
||||||
|
} else {
|
||||||
|
cp->caller = lp ;
|
||||||
|
cp->next = returnto ;
|
||||||
|
returnto = cp ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lp = glp ;
|
lp = glp ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
@ -879,8 +871,15 @@ static int dobuf( buffer_p bp) {
|
||||||
|
|
||||||
break ;
|
break ;
|
||||||
case DRETURN: /* RETURN directive */
|
case DRETURN: /* RETURN directive */
|
||||||
if( execlevel == 0)
|
if( execlevel == 0) {
|
||||||
|
if( returnto != NULL) {
|
||||||
|
caller_p cp = returnto ;
|
||||||
|
lp = returnto->caller ;
|
||||||
|
returnto = returnto->next ;
|
||||||
|
free( cp) ;
|
||||||
|
} else
|
||||||
done = TRUE ;
|
done = TRUE ;
|
||||||
|
}
|
||||||
|
|
||||||
break ;
|
break ;
|
||||||
case DENDWHILE: /* ENDWHILE directive */
|
case DENDWHILE: /* ENDWHILE directive */
|
||||||
|
@ -929,7 +928,8 @@ static int dobuf( buffer_p bp) {
|
||||||
bp->b_doto = 0 ;
|
bp->b_doto = 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
freewhile( whlist) ;
|
freelist( (list_p) returnto) ;
|
||||||
|
freelist( (list_p) whlist) ;
|
||||||
if( einit)
|
if( einit)
|
||||||
free( einit) ;
|
free( einit) ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user