Skip to content

Commit a405343

Browse files
committed
feat: implement #continuedo <number>
1 parent ff45f97 commit a405343

File tree

3 files changed

+167
-9
lines changed

3 files changed

+167
-9
lines changed

check/features.frm

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,11 +2504,91 @@ assert succeeded?
25042504
assert result("F") =~ expr("f(1,2,4,5)")
25052505
*--#] Issue243_1 :
25062506
*--#[ Issue243_2 :
2507-
#continuedo
2507+
NF f;
2508+
L F = 1;
2509+
#define i "9"
2510+
#do i=1,2
2511+
#do i=1,3
2512+
#do i=1,8
2513+
#if `i' == 3
2514+
#continuedo 2
2515+
#endif
2516+
multiply right, f(`i');
2517+
#enddo
2518+
multiply right, f(-`i');
2519+
#enddo
2520+
multiply right, f(-`i');
2521+
#enddo
2522+
multiply right, f(`i');
2523+
chainin f;
2524+
P;
25082525
.end
2509-
assert preprocess_error?
2510-
assert stdout =~ exact_pattern("#continuedo without #do")
2526+
assert succeeded?
2527+
assert result("F") =~ expr("f(1,2,1,2,1,2,-1,1,2,1,2,1,2,-2,9)")
25112528
*--#] Issue243_2 :
2529+
*--#[ Issue243_3 :
2530+
NF f;
2531+
L F = 1;
2532+
#do i=1,3
2533+
#do i=1,2
2534+
#continuedo 0
2535+
multiply right, f(`i');
2536+
#enddo
2537+
#enddo
2538+
chainin f;
2539+
P;
2540+
.end
2541+
assert succeeded?
2542+
assert result("F") =~ expr("f(1,2,1,2,1,2)")
2543+
*--#] Issue243_3 :
2544+
*--#[ Issue243_e1 :
2545+
#continuedo
2546+
.end
2547+
assert preprocess_error?("#continuedo without #do")
2548+
*--#] Issue243_e1 :
2549+
*--#[ Issue243_e2 :
2550+
#do i=1,3
2551+
#continuedo -1
2552+
#enddo
2553+
.end
2554+
assert preprocess_error?("Improper syntax of #continuedo instruction")
2555+
*--#] Issue243_e2 :
2556+
*--#[ Issue243_e3 :
2557+
#do i=1,3
2558+
#continuedo 1a
2559+
#enddo
2560+
.end
2561+
assert preprocess_error?("Improper syntax of #continuedo instruction")
2562+
*--#] Issue243_e3 :
2563+
*--#[ Issue243_e4 :
2564+
#do i=1,3
2565+
#continuedo 2
2566+
#enddo
2567+
.end
2568+
assert preprocess_error?("Too many loop levels requested in #continuedo instruction")
2569+
*--#] Issue243_e4 :
2570+
*--#[ Issue243_e5 :
2571+
#procedure foo
2572+
#continuedo
2573+
#endprocedure
2574+
#do i=1,3
2575+
#call foo
2576+
#enddo
2577+
.end
2578+
assert preprocess_error?("Trying to jump out of a procedure with a #continuedo instruction")
2579+
*--#] Issue243_e5 :
2580+
*--#[ Issue243_e6 :
2581+
#procedure foo
2582+
#continuedo 2
2583+
#endprocedure
2584+
#do i=1,3
2585+
#do j=1,3
2586+
#call foo
2587+
#enddo
2588+
#enddo
2589+
.end
2590+
assert preprocess_error?("Trying to jump out of a procedure with a #continuedo instruction")
2591+
*--#] Issue243_e6 :
25122592
*--#[ Issue392_ContinuationLines_1 :
25132593
#: ContinuationLines 1
25142594
* Setting ContinuationLines to 0 should remove continuation line limit.

doc/manual/prepro.tex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,28 @@ \section{\#commentchar}
632632
The default commentary character is $\ast$.
633633

634634
%--#] commentchar :
635+
%--#[ continuedo :
636+
637+
\section{\#continuedo}
638+
\label{precontinuedo}
639+
640+
\noindent Syntax:
641+
642+
\#continuedo [{\tt<}number{\tt>}]
643+
644+
\noindent See also \#do (\ref{predo}) and \#enddo (\ref{preenddo})
645+
646+
\noindent The \#continuedo\index{\#continuedo} instruction allows one to
647+
jump to the next iteration of a \#do loop.
648+
If a (nonzero integer) number is specified
649+
it indicates the number of enclosing loops
650+
that the program should continue to the next iteration of.
651+
Control will continue at the beginning of the next iteration
652+
of the enclosing loop indicated by `number'.
653+
The default value is one.
654+
If the value is zero the instruction has no effect.
655+
656+
%--#] continuedo :
635657
%--#[ create :
636658

637659
\section{\#create}

sources/pre.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#[ Includes :
3333
*/
3434
#include "form3.h"
35+
#include "comtool.h"
3536
#ifdef WITHFLOAT
3637
#include "math.h"
3738
#endif
@@ -43,6 +44,8 @@ static STREAM *oldstream = 0;
4344
static UBYTE underscore[2] = {'_',0};
4445
static PREVAR *ThePreVar = 0;
4546

47+
static int ExitDoLoops(int, const char *);
48+
4649
static KEYWORD precommands[] = {
4750
{"add" , DoPreAdd , 0, 0}
4851
,{"addseparator" , DoPreAddSeparator,0,0}
@@ -2783,9 +2786,22 @@ int DoTerminate(UBYTE *s)
27832786
#[ DoContinueDo :
27842787
*/
27852788

2789+
/**
2790+
* Jumps forward to the corresponding `#enddo` of the specified number of outer `#do` loops.
2791+
*
2792+
* @par Syntax:
2793+
* @code
2794+
* #continuedo [<number>=1]
2795+
* @endcode
2796+
*
2797+
* If `number` is omitted, it defaults to 1.
2798+
* If `number` is zero then the instruction has no effect.
2799+
*/
27862800
int DoContinueDo(UBYTE *s)
27872801
{
27882802
DOLOOP *loop;
2803+
WORD levels;
2804+
int result;
27892805

27902806
if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
27912807
if ( AP.PreIfStack[AP.PreIfLevel] != EXECUTINGIF ) return(0);
@@ -2795,6 +2811,37 @@ int DoContinueDo(UBYTE *s)
27952811
return(1);
27962812
}
27972813

2814+
SkipSpaces(&s);
2815+
if ( *s == 0 ) {
2816+
levels = 1;
2817+
}
2818+
else if ( FG.cTable[*s] == 1 ) {
2819+
ParseNumber(levels,s);
2820+
SkipSpaces(&s);
2821+
if ( *s != 0 ) goto improper;
2822+
}
2823+
else {
2824+
improper:
2825+
MesPrint("@Improper syntax of %#continuedo instruction");
2826+
return(1);
2827+
}
2828+
2829+
if ( levels > NumDoLoops ) {
2830+
MesPrint("@Too many loop levels requested in %#continuedo instruction");
2831+
return(1);
2832+
}
2833+
2834+
result = ExitDoLoops(levels-1,"continuedo");
2835+
if ( result != 0 ) return(result);
2836+
2837+
if ( levels <= 0 ) return(0);
2838+
2839+
if ( AC.CurrentStream->type == PREREADSTREAM3
2840+
|| AP.PreTypes[AP.NumPreTypes] == PRETYPEPROCEDURE ) {
2841+
MesPrint("@Trying to jump out of a procedure with a %#continuedo instruction");
2842+
return(1);
2843+
}
2844+
27982845
loop = &(DoLoops[NumDoLoops-1]);
27992846
AP.NumPreTypes = loop->NumPreTypes+1;
28002847
AP.PreIfLevel = loop->PreIfLevel;
@@ -3031,7 +3078,6 @@ illdo:;
30313078

30323079
int DoBreakDo(UBYTE *s)
30333080
{
3034-
DOLOOP *loop;
30353081
WORD levels;
30363082

30373083
if ( AP.PreSwitchModes[AP.PreSwitchLevel] != EXECUTINGPRESWITCH ) return(0);
@@ -3062,6 +3108,19 @@ int DoBreakDo(UBYTE *s)
30623108
MesPrint("@Too many loop levels requested in %#breakdo instruction");
30633109
Terminate(-1);
30643110
}
3111+
return(ExitDoLoops(levels,"breakdo"));
3112+
}
3113+
3114+
/**
3115+
* Exits the specified number of nested `#do` loops.
3116+
*
3117+
* @param levels The number of loops to exit.
3118+
* @param instruction The instruction name used for error reporting.
3119+
* @return 0 on success, nonzero on error.
3120+
*/
3121+
static int ExitDoLoops(int levels, const char *instruction)
3122+
{
3123+
DOLOOP *loop;
30653124
while ( levels > 0 ) {
30663125
while ( AC.CurrentStream->type != PREREADSTREAM
30673126
&& AC.CurrentStream->type != PREREADSTREAM2
@@ -3072,16 +3131,13 @@ int DoBreakDo(UBYTE *s)
30723131
&& AP.PreTypes[AP.NumPreTypes] != PRETYPEPROCEDURE ) AP.NumPreTypes--;
30733132
if ( AC.CurrentStream->type == PREREADSTREAM3
30743133
|| AP.PreTypes[AP.NumPreTypes] == PRETYPEPROCEDURE ) {
3075-
MesPrint("@Trying to jump out of a procedure with a %#breakdo instruction");
3076-
Terminate(-1);
3134+
MesPrint("@Trying to jump out of a procedure with a %#%s instruction",instruction);
3135+
return(1);
30773136
}
30783137
loop = &(DoLoops[NumDoLoops-1]);
30793138
AP.NumPreTypes = loop->NumPreTypes;
30803139
AP.PreIfLevel = loop->PreIfLevel;
30813140
AP.PreSwitchLevel = loop->PreSwitchLevel;
3082-
/*
3083-
AP.NumPreTypes--;
3084-
*/
30853141
NumDoLoops--;
30863142
DoUndefine(loop->name);
30873143
M_free(loop->p.buffer,"loop->p.buffer");

0 commit comments

Comments
 (0)