Sona 0.50 Source

Sona 0.50/tools/mml2sona/mml_parse_loop.c

//***************************************************************************
// MML commands handled by this file: [ ] L
//***************************************************************************

#include <stdio.h>
#include "main.h"
#include "mml_parse.h"
#include "mml_parse_loop.h"
#include "stream.h"
#include "text.h"

//***************************************************************************
// parse_repeat [internal]
// Parses repeat loops ([ ... ] command).
//---------------------------------------------------------------------------
// param mml_state: pointer to MML track's state
//---------------------------------------------------------------------------
// return: 0 on success, -1 on syntax error
//***************************************************************************

int parse_repeat(MmlState *mml_state)
{
   // Find the end of the loop
   const char *begin = mml_state->ptr;
   const char *end = begin;
   
   unsigned depth = 1;
   for (;;) {
      char ch = *end++;
      
      // Nested repeat?
      if (ch == '[') {
         depth++;
         continue;
      }
      
      // End of repeat loop?
      if (ch == ']') {
         depth--;
         if (depth == 0) break;
         continue;
      }
      
      // End of track data? (unclosed loop)
      if (end == mml_state->endptr) {
         fprintf(stderr, ERRORMSG_NOREPEATEND,
                 mml_state->filename,
                 mml_state->line_num,
                 mml_state->col_num);
         return -1;
      }
   }
   
   // Update MML state's pointer, and adjust the end of loop pointer to
   // exclude the ] at the end (since we want to measure only the data
   // inside the loop proper)
   mml_state->ptr = end;
   end--;
   
   // Also adjust the column number for the error messages below
   // This points to the ] for consistency with how the other commands
   // are handled (since we pretend that ] is its own command)
   mml_state->col_num += end - begin;
   
   // How many times to repeat the loop?
   int count;
   if (get_number(&mml_state->ptr, &count)) {
      fprintf(stderr, ERRORMSG_NOREPEATCOUNT,
              mml_state->filename,
              mml_state->line_num,
              mml_state->col_num);
      return -1;
   }
   if (count < 0) {
      fprintf(stderr, ERRORMSG_BADREPEATCOUNT,
              mml_state->filename,
              mml_state->line_num,
              mml_state->col_num,
              count);
      return -1;
   }
   
   // Now execute all the commands within the repeat loop
   const char *backup_ptr = mml_state->ptr;
   const char *backup_endptr = mml_state->endptr;
   int errored = 0;
   
   while (count > 0) {
      count--;
      
      mml_state->ptr = begin;
      mml_state->endptr = end;
      errored |= parse_mml_subloop(mml_state);
   }
   
   mml_state->ptr = backup_ptr;
   mml_state->endptr = backup_endptr;
   
   // Done
   return errored;
}

//***************************************************************************
// parse_loop_point [internal]
// Parses the loop point for the entire stream (L command).
//---------------------------------------------------------------------------
// param mml_state: pointer to MML track's state
//---------------------------------------------------------------------------
// return: 0 on success, -1 on syntax error
//***************************************************************************

int parse_loop_point(MmlState *mml_state)
{
   // Add set loop event
   Stream *stream = mml_state->stream;
   Event *event = create_event(stream);
   event->type = EVENT_LOOP;
   
   // Mark stream as looping
   stream->looped = 1;
   
   // Always succeed for now
   return 0;
}