// File: /workspace/github_cpp_makefile_star2_O3/mikeakohn[P]drumsplusplus/build/../src/Song.cxx
// Function: Song::parse_pattern(Tokens*)
int Song::parse_pattern(Tokens *tokens)
{
  int token_type;
  char token[1024], token1[1024];
  Beat beats[256];
  int ptr;
  char value[1024];
  float low_beat = 0;
  float next_beat = 0;
  int i, count, num_notes;
  int beat_time;
  int time_signature_beats;
  //int time_signature_base;
  int midi_channel;

  beat_time = 60000000 / song_info.bpm;
  time_signature_beats = song_info.time_signature_beats;
  //time_signature_base = song_info.time_signature_base;
  midi_channel = song_info.midi_channel;

  token_type = tokens->get(token);

  if (token_type != TOKEN_ALPHA)
  {
    printf("Error: Pattern is not alphanumeric at %s:%d\n",
      tokens->get_filename(), tokens->get_line());
    return -1;
  }

  if (patterns.find(token) != patterns.end())
  {
    printf("Error: Pattern %s is already defined at %s:%d\n",
      token, tokens->get_filename(), tokens->get_line());
    return -1;
  }

  std::string pattern_name = token;

  const int index = patterns.size();
  Pattern &pattern = patterns[pattern_name];

  pattern_names[index] = token;

  pattern.set_name(pattern_name);
  pattern.set_index(index);

#ifdef DEBUG
printf("parsing pattern: %s %d\n", token, index);
#endif

  token_type = tokens->get(token);

  if (strcmp(token, "{") != 0)
  {
    print_error(tokens, "{", token);
    return -1;
  }

  ptr = 0;
  num_notes = 0;

  while(1)
  {
    token_type = tokens->get(token);

    if (strcmp(token, "}") == 0) { break;}

    // Check if there are some modifications to the global song values.
    if (strcmp(token, "set") == 0)
    {
      token_type = tokens->get(token);

      if (token_type != TOKEN_ALPHA)
      {
        print_error(tokens, "variable to set", token);
        return -1;
      }

      token_type = tokens->get(token1);

      if (strcmp(token1, "=") != 0)
      {
        print_error(tokens, "=", token1);
        return -1;
      }

      token_type = tokens->get(token1);

      if (token_type != TOKEN_NUMBER)
      {
        print_error(tokens, "a number", token1);
        return -1;
      }

      i = atoi(token1);

      if (i == 0)
      {
        print_error(tokens, "a non-zero integer", token1);
        return -1;
      }

      if (strcmp(token, "bpm") == 0)
      {
        beat_time = 60000000 / i;
      }
        else
      if (strcmp(token, "timesignature") == 0)
      {
        time_signature_beats = i;

        token_type = tokens->get(token1);

        if (strcmp(token1, "/") != 0)
        {
          print_error(tokens, "/", token1);
          return -1;
        }

        token_type = tokens->get(token1);

        if (token_type != TOKEN_NUMBER)
        {
          print_error(tokens, "a number", token1);
          return -1;
        }

        i = atoi(token1);

        if (i == 0)
        {
          print_error(tokens, "a non-zero integer", token1);
          return -1;
        }

        //time_signature_base = i;
      }
        else
      if (strcmp(token, "midi_channel") == 0)
      {
        midi_channel = i;

        if (midi_channel > 15)
        {
          printf("Warning: MIDI channel %d is higher than max 15; line %d\n",
            midi_channel, tokens->get_line());
          midi_channel = 9;
        }
      }
        else
      {
        printf("Warning: Cannot set '%s' in pattern.\n", token);
      }

      token_type = tokens->get(token);

      if (strcmp(token, ";") != 0)
      {
        print_error(tokens, ";", token);
        return -1;
      }

      continue;
    }

    // Read next line of beat information for an instrument from a pattern.
    if (token_type == TOKEN_NUMBER)
    {
      beats[ptr].channel = midi_channel;

      if (add_beats(tokens, beats, ptr, atoi(token), midi_channel) == -1)
      {
        return -1;
      }
    }
      else
    {
      if (defines.find(token) == defines.end())
      {
        printf("Error: %s is undefined at %s:%d\n",
          token, tokens->get_filename(), tokens->get_line());
        return -1;
      }

      strcpy(value, defines[token].c_str());

      if (Utility::is_number(value) == false)
      {
        printf("Error: %s is not a number at %s:%d\n",
          token, tokens->get_filename(), tokens->get_line());
        return -1;
      }

      beats[ptr].channel = midi_channel;

      if (add_beats(tokens, beats, ptr, atoi(value), midi_channel) == -1)
      {
        return -1;
      }
    }
  }

#ifdef DEBUG
for (int n = 0; n < ptr; n++)
{
  printf("beat: %d %d %f %d\n",
    beats[n].instrument,
    beats[n].channel,
    beats[n].value,
    beats[n].volume);
}
#endif

  // Convert beat information to the pattern format.  This looks like
  // basically a slow sorting algorithm.
  while(1)
  {
    low_beat = time_signature_beats + 1;
    next_beat = time_signature_beats + 1;
    count = 0;

    // Find the next lowest beat value and a count of how many
    // times that beat value exists.
    for (i = 0; i < ptr; i++)
    {
      if (beats[i].value > 0)
      {
        if (beats[i].value < low_beat)
        {
          low_beat = beats[i].value;
          count = 0;
        }

        if (beats[i].value == low_beat) { count++; }
      }
    }

    // If no more beats were found, break from adding to the pattern list.
    if (count == 0)
    {
      if (ptr == 0)
      {
        // If this is the first beat, add an empty pattern?
        int duration = (int)((time_signature_beats) * beat_time);

        pattern.add(0, 0, midi_channel, duration);
      }

      break;
    }

    // Find the next lowest value.  It seems like this whole process
    // could be done without doing this.
    for (i = 0; i < ptr; i++)
    {
      if (beats[i].value > 0)
      {
        if (beats[i].value < next_beat && beats[i].value != low_beat)
        {
          next_beat = beats[i].value;
        }
      }
    }

    // Scan through all the beats, and if it is equal to the current
    // lowest, add it to the pattern.  Then clear it out so it doesn't
    // get counted again.
    for (i = 0; i < ptr; i++)
    {
      if (beats[i].value == low_beat)
      {
        if (num_notes == 0 && low_beat != 1)
        {
          int duration = (int)((low_beat - 1) * beat_time);

          pattern.add(0, 0, midi_channel, duration);
        }

        int duration = 0;


        if (count == 1)
        {
          duration = (int)((next_beat - low_beat) * beat_time);
        }

        pattern.add(beats[i].instrument,
                    beats[i].volume,
                    beats[i].channel,
                    duration);

        beats[i].value = 0;

        count--;
      }
    }

    num_notes++;
  }

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1c98, %rsp           # imm = 0x1C98
movq %rdi, %r13
movl $0x3938700, %eax        # imm = 0x3938700
xorl %edx, %edx
idivl 0x20(%rdi)
movl %eax, %ebp
movq %rsi, %r12
movl 0x2c(%rdi), %r15d
movl 0x34(%rdi), %r14d
leaq 0x90(%rsp), %rsi
movq %r12, %rdi
callq 0x2884
cmpl $0x1, %eax
jne 0x3e8a
leaq 0x50(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x90(%rsp), %rbx
movq %rbx, %rdi
callq 0x20e0
leaq (%rsp,%rax), %rdx
addq $0x90, %rdx
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
callq 0x61de
movq %r15, 0x80(%rsp)
movl %r14d, 0x1c(%rsp)
leaq 0x78(%r13), %rbx
leaq 0x40(%rsp), %rsi
movq %rbx, %rdi
callq 0x6586
movq %rax, %r14
leaq 0x80(%r13), %r15
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x3e63
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x21b0
cmpq %r15, %r14
je 0x3ebb
movq 0x8(%r12), %rdx
movl 0x2c(%r12), %ecx
leaq 0x3847(%rip), %rdi      # 0x76c0
leaq 0x90(%rsp), %rsi
xorl %eax, %eax
callq 0x2050
jmp 0x3ea2
movq 0x8(%r12), %rsi
movl 0x2c(%r12), %edx
leaq 0x37f8(%rip), %rdi      # 0x7693
xorl %eax, %eax
callq 0x2050
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl %ebx, %eax
addq $0x1c98, %rsp           # imm = 0x1C98
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x40(%rsp), %r14
leaq 0x50(%rsp), %rax
movq %rax, (%r14)
leaq 0x90(%rsp), %r15
movq %r15, %rdi
callq 0x20e0
leaq (%rsp,%rax), %rdx
addq $0x90, %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x61de
movl %ebp, 0x18(%rsp)
movl 0xa0(%r13), %eax
movl %eax, 0x3c(%rsp)
leaq 0x40(%rsp), %rsi
movq %rbx, %rdi
callq 0x5616
movq %rax, 0x28(%rsp)
movl 0x1c(%rsp), %r15d
leaq 0xd8(%r13), %rdi
leaq 0x3c(%rsp), %rsi
callq 0x55b0
movq %rax, %rbx
movq 0x8(%rax), %r14
leaq 0x90(%rsp), %rbp
movq %rbp, %rdi
callq 0x20e0
movq %rbx, %rdi
xorl %esi, %esi
movq %r14, %rdx
movq %rbp, %rcx
movq %rax, %r8
callq 0x22b0
leaq 0x40(%rsp), %rsi
movq 0x28(%rsp), %rdi
callq 0x2100
movl 0x3c(%rsp), %eax
movq 0x28(%rsp), %rcx
movl %eax, 0x38(%rcx)
leaq 0x90(%rsp), %rsi
movq %r12, %rdi
callq 0x2884
cmpw $0x7b, 0x90(%rsp)
jne 0x430e
leaq 0xc(%rsp), %rax
movl $0x0, (%rax)
leaq 0xa8(%r13), %rbx
leaq 0xb0(%r13), %rax
movq %rax, 0x10(%rsp)
leaq 0x60(%rsp), %rbp
movq %r12, %rdi
leaq 0x90(%rsp), %rsi
callq 0x2884
cmpw $0x7d, 0x90(%rsp)
je 0x433a
cmpl $0x746573, 0x90(%rsp) # imm = 0x746573
je 0x4153
cmpl $0x2, %eax
jne 0x4022
movslq 0xc(%rsp), %rax
shlq $0x4, %rax
movl %r15d, 0xc98(%rsp,%rax)
leaq 0x90(%rsp), %rdi
callq 0x22c0
movq %r13, %rdi
movq %r12, %rsi
leaq 0xc90(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movl %eax, %r8d
movl %r15d, %r9d
callq 0x4f94
jmp 0x4145
leaq 0x70(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x90(%rsp), %r14
movq %r14, %rdi
callq 0x20e0
leaq (%rsp,%rax), %rdx
addq $0x90, %rdx
movq %rbp, %rdi
movq %r14, %rsi
callq 0x61de
movq %rbp, %rsi
movq %rbx, %r14
movq %rbx, %rdi
callq 0x6154
movq %rax, %rbx
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x407f
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x21b0
cmpq 0x10(%rsp), %rbx
je 0x4559
leaq 0x70(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x90(%rsp), %rbx
movq %rbx, %rdi
callq 0x20e0
leaq (%rsp,%rax), %rdx
addq $0x90, %rdx
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x61de
movq %r14, %rbx
movq %r14, %rdi
movq %rbp, %rsi
callq 0x5692
movq (%rax), %rsi
leaq 0x890(%rsp), %rdi
callq 0x2170
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x40f4
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x21b0
leaq 0x890(%rsp), %rdi
callq 0x6c3c
testb %al, %al
je 0x456c
movslq 0xc(%rsp), %rax
shlq $0x4, %rax
movl %r15d, 0xc98(%rsp,%rax)
leaq 0x890(%rsp), %rdi
callq 0x22c0
movq %r13, %rdi
movq %r12, %rsi
leaq 0xc90(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movl %eax, %r8d
movl %r15d, %r9d
callq 0x4f94
cmpl $-0x1, %eax
jne 0x3fac
jmp 0x458c
movq %r12, %rdi
leaq 0x90(%rsp), %rsi
callq 0x2884
cmpl $0x1, %eax
jne 0x45ea
movq %r12, %rdi
leaq 0x490(%rsp), %rsi
callq 0x2884
cmpw $0x3d, 0x490(%rsp)
jne 0x4607
movq %r12, %rdi
leaq 0x490(%rsp), %rsi
callq 0x2884
cmpl $0x2, %eax
jne 0x45b6
leaq 0x490(%rsp), %rdi
callq 0x22c0
testl %eax, %eax
je 0x45d0
movl %eax, %r14d
cmpl $0x6d7062, 0x90(%rsp) # imm = 0x6D7062
jne 0x41dc
movl $0x3938700, %eax        # imm = 0x3938700
xorl %edx, %edx
idivl %r14d
movl %eax, 0x18(%rsp)
jmp 0x42d5
movq 0x90(%rsp), %rax
movabsq $0x6e676973656d6974, %rcx # imm = 0x6E676973656D6974
xorq %rcx, %rax
movq 0x96(%rsp), %rcx
movabsq $0x65727574616e67, %rdx # imm = 0x65727574616E67
xorq %rdx, %rcx
orq %rax, %rcx
je 0x4255
movq 0x90(%rsp), %rax
movabsq $0x6168635f6964696d, %rcx # imm = 0x6168635F6964696D
xorq %rcx, %rax
movq 0x95(%rsp), %rcx
movabsq $0x6c656e6e616863, %rdx # imm = 0x6C656E6E616863
xorq %rdx, %rcx
orq %rax, %rcx
je 0x42ae
leaq 0x3515(%rip), %rdi      # 0x7756
leaq 0x90(%rsp), %rsi
xorl %eax, %eax
callq 0x2050
jmp 0x42d5
movq %r12, %rdi
leaq 0x490(%rsp), %rsi
callq 0x2884
cmpw $0x2f, 0x490(%rsp)
jne 0x462c
movq %r12, %rdi
leaq 0x490(%rsp), %rsi
callq 0x2884
cmpl $0x2, %eax
jne 0x45b6
leaq 0x490(%rsp), %rdi
callq 0x22c0
movl %r14d, %ecx
movq %rcx, 0x80(%rsp)
testl %eax, %eax
jne 0x42d5
jmp 0x45d0
cmpl $0x10, %r14d
jl 0x42d2
movl 0x2c(%r12), %edx
leaq 0x345d(%rip), %rdi      # 0x771d
movl %r14d, %esi
xorl %eax, %eax
callq 0x2050
movl $0x9, %r15d
jmp 0x42d5
movl %r14d, %r15d
movq %r12, %rdi
leaq 0x90(%rsp), %rsi
callq 0x2884
cmpw $0x3b, 0x90(%rsp)
je 0x3fac
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x35db(%rip), %rdi      # 0x78e0
leaq 0x3210(%rip), %rsi      # 0x751c
jmp 0x4326
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x35c1(%rip), %rdi      # 0x78e0
leaq 0x33c9(%rip), %rsi      # 0x76ef
leaq 0x90(%rsp), %rdx
xorl %eax, %eax
callq 0x2050
jmp 0x458c
movl 0xc(%rsp), %eax
movq %rax, 0x20(%rsp)
testl %eax, %eax
movl 0x18(%rsp), %ecx
jle 0x452d
movq 0x80(%rsp), %rax
incl %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x38(%rsp)
xorps %xmm0, %xmm0
cvtsi2ss %ecx, %xmm0
movss %xmm0, 0x88(%rsp)
movq 0x20(%rsp), %r13
shlq $0x4, %r13
xorl %edx, %edx
movzbl %r15b, %eax
movl %eax, 0x8c(%rsp)
movl $0x0, 0x34(%rsp)
movl %r15d, 0x1c(%rsp)
xorl %eax, %eax
movss 0x38(%rsp), %xmm0
movss %xmm0, 0x10(%rsp)
xorl %ebx, %ebx
movss 0xc90(%rsp,%rax), %xmm1
ucomiss 0x2f5a(%rip), %xmm1     # 0x7310
jbe 0x43da
movss 0x10(%rsp), %xmm2
ucomiss %xmm1, %xmm2
cmoval %edx, %ebx
movaps %xmm1, %xmm0
minss %xmm2, %xmm0
ucomiss %xmm0, %xmm1
jne 0x43d4
jp 0x43d4
incl %ebx
movss %xmm0, 0x10(%rsp)
addq $0x10, %rax
cmpq %rax, %r13
jne 0x43a6
testl %ebx, %ebx
je 0x452d
cmpl $0x0, 0x20(%rsp)
jle 0x4510
xorl %eax, %eax
movss 0x38(%rsp), %xmm0
movss 0xc90(%rsp,%rax), %xmm1
movaps %xmm1, %xmm2
cmpltps %xmm0, %xmm2
xorps %xmm3, %xmm3
cmpltps %xmm1, %xmm3
andps %xmm2, %xmm3
movd %xmm3, %ecx
testb $0x1, %cl
je 0x443a
movaps %xmm1, %xmm2
cmpneqss 0x10(%rsp), %xmm2
movaps %xmm2, %xmm3
andps %xmm1, %xmm3
andnps %xmm0, %xmm2
orps %xmm3, %xmm2
movaps %xmm2, %xmm0
addq $0x10, %rax
cmpq %rax, %r13
jne 0x43fe
cmpl $0x0, 0x20(%rsp)
jle 0x4510
cmpl $0x0, 0x34(%rsp)
sete %al
movss 0x10(%rsp), %xmm3
ucomiss 0x2ea5(%rip), %xmm3     # 0x7308
setp %cl
setne %r15b
orb %cl, %r15b
andb %al, %r15b
movaps %xmm3, %xmm1
addss 0x2e91(%rip), %xmm1     # 0x730c
movss 0x88(%rsp), %xmm2
mulss %xmm2, %xmm1
cvttss2si %xmm1, %r14d
subss %xmm3, %xmm0
mulss %xmm2, %xmm0
cvttss2si %xmm0, %r12d
xorl %ebp, %ebp
movss 0xc90(%rsp,%rbp), %xmm0
ucomiss 0x10(%rsp), %xmm0
jne 0x4507
jp 0x4507
testb %r15b, %r15b
je 0x44cb
movq 0x28(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
movl 0x8c(%rsp), %ecx
movl %r14d, %r8d
callq 0x312a
cmpl $0x1, %ebx
movl $0x0, %r8d
cmovel %r12d, %r8d
movzbl 0xc94(%rsp,%rbp), %esi
movzbl 0xc9c(%rsp,%rbp), %edx
movzbl 0xc98(%rsp,%rbp), %ecx
movq 0x28(%rsp), %rdi
callq 0x312a
movl $0x0, 0xc90(%rsp,%rbp)
decl %ebx
addq $0x10, %rbp
cmpq %rbp, %r13
jne 0x449c
incl 0x34(%rsp)
cmpl $0x0, 0x20(%rsp)
movl 0x18(%rsp), %ecx
movl 0x1c(%rsp), %r15d
movl $0x0, %edx
jg 0x4396
xorl %ebx, %ebx
cmpq $0x0, 0x20(%rsp)
jne 0x4591
movq 0x80(%rsp), %r8
imull %ecx, %r8d
xorl %ebx, %ebx
movzbl %r15b, %ecx
movq 0x28(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x312a
jmp 0x4591
movq 0x8(%r12), %rdx
movl 0x2c(%r12), %ecx
leaq 0x3212(%rip), %rdi      # 0x777c
jmp 0x457d
movq 0x8(%r12), %rdx
movl 0x2c(%r12), %ecx
leaq 0x3220(%rip), %rdi      # 0x779d
leaq 0x90(%rsp), %rsi
xorl %eax, %eax
callq 0x2050
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x3ea7
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x21b0
jmp 0x3ea7
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x3319(%rip), %rdi      # 0x78e0
leaq 0x3133(%rip), %rsi      # 0x7701
jmp 0x461f
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x32ff(%rip), %rdi      # 0x78e0
leaq 0x3122(%rip), %rsi      # 0x770a
jmp 0x461f
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x32e5(%rip), %rdi      # 0x78e0
leaq 0x30ef(%rip), %rsi      # 0x76f1
jmp 0x4326
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x32c8(%rip), %rdi      # 0x78e0
leaq 0x2d62(%rip), %rsi      # 0x7381
leaq 0x490(%rsp), %rdx
jmp 0x432e
movq 0x8(%r12), %rcx
movl 0x2c(%r12), %r8d
leaq 0x32a3(%rip), %rdi      # 0x78e0
leaq 0x2dea(%rip), %rsi      # 0x742e
jmp 0x461f
jmp 0x4680
jmp 0x4680
jmp 0x4675
jmp 0x4650
jmp 0x4680
movq %rax, %rbx
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x4683
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x21b0
jmp 0x4683
jmp 0x4680
jmp 0x4680
movq %rax, %rbx
jmp 0x469f
jmp 0x4680
jmp 0x4680
jmp 0x4680
movq %rax, %rbx
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x469f
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x21b0
movq %rbx, %rdi
callq 0x2300
nop