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;
4344static UBYTE underscore [2 ] = {'_' ,0 };
4445static PREVAR * ThePreVar = 0 ;
4546
47+ static int ExitDoLoops (int , const char * );
48+
4649static 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+ */
27862800int 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
30323079int 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