Revise directive parsing and processing.

Allow multi line comment using !store without procedure name (think about #if 0).
This commit is contained in:
Renaud 2021-09-10 10:10:19 +08:00
parent 81d6f76c78
commit 78e296afbb
1 changed files with 113 additions and 114 deletions

227
exec.c
View File

@ -8,6 +8,7 @@
modified by Petri Kutvonen
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@ -30,17 +31,17 @@ 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 DGOSUB 10
#define DFORCE 0
#define DGOTO 1
#define DGOSUB 2
#define DIF 3
#define DWHILE 4
#define DBREAK 5
#define DELSE 6
#define DENDIF 7
#define DENDM 8
#define DENDWHILE 9
#define DRETURN 10
typedef struct caller {
@ -66,9 +67,9 @@ typedef struct while_block {
/* directive name table: holds the names of all the directives.... */
static const char *dname[] = {
"if", "else", "endif", "goto", "return",
"endm", "while", "endwhile", "break", "force",
"gosub"
"force", "goto", "gosub", "if", "while",
"break", "else", "endif", "endm", "endwhile",
"return"
} ;
#define NUMDIRS ARRAY_SIZE( dname)
@ -528,6 +529,7 @@ static int dobuf( buffer_p bp) {
while_p whtemp ; /* temporary ptr to a struct while_block */
char *eline ; /* text of line to execute */
char tkn[ NSTRING] ; /* buffer to evaluate an expression in */
int w_type ; /* either while or break */
/* clear IF level flags/while ptr */
while_p whlist = NULL ; /* ptr to !WHILE list */
@ -570,7 +572,7 @@ static int dobuf( buffer_p bp) {
if( !strncmp( eline, "!endm", 5)) {
bstore = NULL ;
storing_f = FALSE ;
} else if( !storeline( lp->l_text, lp->l_used))
} else if( bstore && !storeline( lp->l_text, lp->l_used))
goto failexit ;
/* remove line */
@ -593,19 +595,31 @@ static int dobuf( buffer_p bp) {
continue ;
if( !strncmp( eline, "!store", 6)) {
if( lp->l_used < lp->l_size) {
eline[ lp->l_used] = 0 ;
token( &eline[ 6], &tkn[ 1], sizeof tkn - 1) ;
char c = tkn[ 1] ;
if( c >= '1' && c <= '9') { /* number >= 1 */
if( !storemac( TRUE, atoi( &tkn[ 1])))
goto failexit ;
} else { /* whatever */
*tkn = '*' ;
strcat( tkn, "*") ;
if( !setstore( tkn))
goto failexit ;
}
/* turn line into a string */
int size = lp->l_used - 6 ;
if( size)
memcpy( lp->l_text, &eline[ 6], size) ;
eline = lp->l_text ;
eline[ size] = 0 ;
lp->l_used = size ;
/* get procedure or macro name */
token( eline, &tkn[ 1], sizeof tkn - 1) ;
char c = tkn[ 1] ;
if( !c || c == '#' || c == ';') {
/* no name */
storing_f = TRUE ; /* just throw away the lines (no bstore) */
} else if( c >= '1' && c <= '9') { /* number >= 1 */
/* macro number */
if( !storemac( TRUE, atoi( &tkn[ 1])))
goto failexit ;
} else {
/* whatever */
*tkn = '*' ;
strcat( tkn, "*") ;
if( !setstore( tkn))
goto failexit ;
}
/* remove line */
@ -614,15 +628,16 @@ static int dobuf( buffer_p bp) {
continue ;
} else if( !strncmp( eline, "!while", 6)) {
/* if it is a while directive, make a block... */
w_type = BTWHILE ;
scan:
whtemp = malloc( sizeof *whtemp) ;
if( whtemp == NULL) {
noram:
mloutstr( "%%Out of memory during while scan") ;
goto failexit ;
}
}
whtemp->w_begin = lp ;
whtemp->w_type = BTWHILE ;
whtemp->w_type = w_type ;
whtemp->w_next = scanner ;
scanner = whtemp ;
} else if( !strncmp( eline, "!break", 6)) {
@ -632,14 +647,8 @@ static int dobuf( buffer_p bp) {
goto failexit ;
}
whtemp = malloc( sizeof *whtemp) ;
if( whtemp == NULL)
goto noram ;
whtemp->w_begin = lp ;
whtemp->w_type = BTBREAK ;
whtemp->w_next = scanner ;
scanner = whtemp ;
w_type = BTBREAK ;
goto scan ;
} else if( !strncmp( eline, "!endwhile", 9)) {
/* if it is an endwhile directive, record the spot... */
if( scanner == NULL) {
@ -682,28 +691,25 @@ static int dobuf( buffer_p bp) {
/* starting at the beginning of the buffer */
char *einit = NULL ; /* initial value of eline */
int esize = 0 ; /* size available for storage in einit */
int status = TRUE ; /* status of command execution */
boolean done = FALSE ;
int execlevel = 0 ; /* execution IF level */
caller_p returnto = NULL ;
line_p lp = hlp->l_fp ;
for( ; lp != hlp ; lp = lp->l_fp) {
if( einit) {
free( einit) ;
einit = NULL ;
}
/* allocate eline and copy macro line to it */
int linlen = lp->l_used ;
if( linlen == 0)
continue ;
einit = eline = malloc( linlen + 1) ;
if( eline == NULL) {
status = mloutfail( "%%Out of Memory during macro execution") ;
break ;
}
if( esize <= linlen) {
esize = linlen + 1 ;
einit = realloc( einit, esize) ;
if( einit == NULL) {
status = mloutfail( "%%Out of Memory during macro execution") ;
break ;
}
}
eline = einit ;
memcpy( eline, lp->l_text, linlen) ;
eline[ linlen] = 0 ;
@ -729,13 +735,16 @@ static int dobuf( buffer_p bp) {
if( !strncmp( eline, "!endm", 5)) {
storing_f = FALSE ;
bstore = NULL ;
lp = lp->l_bp ;
lfree( lp->l_fp) ;
} else {
status = storeline( eline, strlen( eline)) ;
if( status != TRUE)
break ;
}
lp->l_used = 0 ;
lp = lp->l_bp ;
lfree( lp->l_fp) ;
continue ;
}
@ -759,75 +768,83 @@ static int dobuf( buffer_p bp) {
break ;
}
--eline ; /* restore the original eline.... */
/* now, execute directives */
/* skip past the directive */
while( *eline && *eline != ' ' && *eline != '\t')
++eline ;
/* skip past the directives that takes arguments */
if( dirnum <= DWHILE) {
while( *eline && *eline != ' ' && *eline != '\t')
++eline ;
while( *eline && (*eline == ' ' || *eline == '\t'))
++eline ;
while( *eline && (*eline == ' ' || *eline == '\t'))
++eline ;
execstr = eline ;
}
execstr = eline ;
switch( dirnum) {
case DENDM:
if( execlevel == 0)
status = mloutfail( "!endm out of context") ;
break ;
case DIF: /* IF directive */
/* grab the value of the logical exp */
if( execlevel == 0) {
/* grab the value of the logical exp */
status = macarg( tkn, sizeof tkn) ;
if( status == TRUE && stol( tkn) == FALSE)
++execlevel ;
execlevel = 1 ; /* skip to else or endif */
} else
++execlevel ;
break ;
case DWHILE: /* WHILE directive */
/* grab the value of the logical exp */
if( execlevel == 0) {
status = macarg( tkn, sizeof tkn) ;
if( status != TRUE) {
break ;
} else if( stol( tkn) == TRUE)
break ;
}
/* drop down and act just like !BREAK */
/* fallthrough */
case DBREAK: /* BREAK directive */
if( dirnum == DBREAK && execlevel)
continue ;
/* jump down to the endwhile */
/* find the right while loop */
for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next)
if( whtemp->w_begin == lp)
break ;
if( whtemp == NULL)
status = mloutfail( "%%Internal While loop error") ;
else
/* reset the line pointer back.. */
lp = whtemp->w_end ;
break ;
case DELSE: /* ELSE directive */
if( execlevel == 1)
--execlevel ;
execlevel = 0 ; /* execute the else part */
else if( execlevel == 0)
++execlevel ;
execlevel = 1 ; /* skip to endif */
/* else keep skipping */
break ;
case DENDIF: /* ENDIF directive */
if( execlevel)
--execlevel ;
break ;
case DWHILE: /* WHILE directive */
if( execlevel == 0) {
/* grab the value of the logical exp */
status = macarg( tkn, sizeof tkn) ;
if( status != TRUE || stol( tkn) == TRUE)
break ;
}
/* fallthrough */
case DBREAK: /* BREAK directive */
/* jump down to the endwhile */
/* find the right while loop */
for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next)
if( whtemp->w_begin == lp) {
/* reset the line pointer back.. */
lp = whtemp->w_end ;
break ;
}
if( whtemp == NULL)
status = mloutfail( "%%Internal While loop error") ;
break ;
case DENDWHILE: /* ENDWHILE directive */
assert( execlevel == 0) ;
/* find the right while loop */
for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next)
if( whtemp->w_type == BTWHILE && whtemp->w_end == lp) {
/* reset the line pointer back.. */
lp = whtemp->w_begin->l_bp ;
break ;
}
if( whtemp == NULL)
status = mloutfail( "%%Internal While loop error") ;
break ;
case DGOSUB: /* GOSUB directive */
case DGOTO: /* GOTO directive */
@ -881,24 +898,6 @@ static int dobuf( buffer_p bp) {
done = TRUE ;
}
break ;
case DENDWHILE: /* ENDWHILE directive */
if( execlevel)
--execlevel ;
else {
/* find the right while loop */
for( whtemp = whlist ; whtemp ; whtemp = whtemp->w_next)
if( whtemp->w_type == BTWHILE
&& whtemp->w_end == lp)
break ;
if( whtemp == NULL)
status = mloutfail( "%%Internal While loop error") ;
else
/* reset the line pointer back.. */
lp = whtemp->w_begin->l_bp ;
}
break ;
case DFORCE: /* FORCE directive */
if( execlevel == 0)