// File: /workspace/github_c_makefile_star2_O2/mmayer[P]pcal/src/readfile.c
// Function: parse_rel
int parse_rel (int val, int wkd, char **pword, int *ptype, char ***pptext)
{
   int prep, n, rtn, base_wkd, incr = 1, (*pfcn) (int, int, int);
   date_str *pd;
   
   /* we have the weekday - now look for the preposition */
   if ((prep = get_prep(*pword++)) == PR_OTHER) return PARSE_INVLINE;

   /* get the base date */
   if ((rtn = parse_date(pword, ptype, pptext)) != PARSE_OK) return rtn;

   /* transform 'candidate_dates' array in place - note that the relative date may not
      be in the same month or even year */
   
   if (IS_WILD(wkd)) {   /* wildcard for weekday name? */
      pfcn = pdatefcn[wkd - WILD_FIRST];
      
      for (pd = candidate_dates; pd->mm; pd++) {
         
         /* search for nearest matching date */
         
         switch (prep) {
         case PR_BEFORE:
            pd->dd -= 1;   /* start with previous date */
            normalize(pd);
            /* fall through */
         case PR_ON_BEFORE:
            incr = -1;   /* search backwards */
            break;
            
         case PR_AFTER:
            pd->dd += 1;   /* start with following date */
            normalize(pd);
            /* fall through */
         case PR_ON_AFTER:
            incr = 1;   /* search forward */
            break;
            
         case PR_NEAREST:
            /* If NEAREST_INCR (cf. pcaldefs.h) is 1, pcal will disambiguate
               "nearest" in favor of the later date; if -1, in favor of the
               earlier.  "incr" will take the values 1, -2, 3, -4, ... or -1,
               2, -3, 4 ...  respectively during the search loop below.
              
               ("nearest_before" and "nearest_after" were added to v4.6 to
               allow the user to specify disambiguation of two equally near
               dates.)
            */
            incr = NEAREST_INCR;
            val = 1;   /* ordinals meaningless here */
            break;
            
         case PR_NEAREST_BEFORE:
            incr = -1;   /* start searching backward */
            val = 1;   /* ordinals meaningless here */
            break;

         case PR_NEAREST_AFTER:
            incr = 1;   /* start searching forward */
            val = 1;   /* ordinals meaningless here */
            break;
         }
         
         n = val;
         while (!((*pfcn)(pd->mm, pd->dd, pd->yy) && --n == 0)) {
            pd->dd += incr;
            normalize(pd);
            /* if searching for "nearest" date, invert sign and bump magnitude
               of 'incr' on each pass
            */
            if (prep == PR_NEAREST || prep == PR_NEAREST_BEFORE || prep == PR_NEAREST_AFTER) {
               incr -= (incr > 0) ? (2 * incr + 1) : (2 * incr - 1);
            }
         }
      }

   }
   else  {   /* explicit weekday name */
      for (pd = candidate_dates; pd->mm; pd++) {
         
         /* calculate nearest matching weekday - note that "nearest_before"
           and "nearest_after" are synonyms for "before" and "after"
         */

         base_wkd = calc_weekday(pd->mm, pd->dd, pd->yy);
         switch (prep) {
         case PR_BEFORE:
         case PR_NEAREST_BEFORE:
         case PR_ON_BEFORE:
            if (prep != PR_ON_BEFORE || wkd != base_wkd) pd->dd -= 7 - (wkd - base_wkd + 7) % 7;
            pd->dd -= 7 * (val - 1);
            break;
            
         case PR_AFTER:
         case PR_NEAREST_AFTER:
         case PR_ON_AFTER:
            if (prep != PR_ON_AFTER || wkd != base_wkd) pd->dd += (wkd - base_wkd + 6) % 7 + 1;
            pd->dd += 7 * (val - 1);
            break;
            
         case PR_NEAREST:
            /* use closer of previous and next */
            val = wkd - base_wkd;
            pd->dd += (val > 3) ? (val - 7) : (val < -3) ? (val + 7) : val;
            break;

         case PR_ON:
            /*
              The 'on' preposition is a special case.  When the conditions it
              specifies are not matched, we really need to actually _remove_
              this entry from the 'candidate dates' array.
              
              However, for now, it's easier to just set the 'year' ('yy')
              field in the 'candidate dates' array to -1, as a flag to ignore
              this date entry entirely when later adding events to the big
              linked list based on entries from this 'candidate dates' array.
            */
            if (wkd != base_wkd) {
               pd->yy = -1;  /* invalidate this 'candidate date' entry... */
            }
            break;

         default:
            return PARSE_INVLINE;
            break;
         }
         
         normalize(pd);   /* adjust for month/year crossing */
      }
   }
   
   return PARSE_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %r8, %r12
movq %rcx, %r13
movq %rdx, %rbp
movl %esi, %r15d
movl %edi, %r14d
movq (%rdx), %rdi
callq 0xc187
movl %eax, %ebx
pushq $0x2
popq %rax
cmpl $-0x1, %ebx
je 0xd4df
addq $0x8, %rbp
movq %rbp, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0xc9b3
testl %eax, %eax
jne 0xd4df
leal -0x7(%r15), %eax
cmpl $0xb, %eax
jae 0xd3ed
movl %eax, %eax
leaq 0x1aebe(%rip), %rcx     # 0x281e0
movq (%rcx,%rax,8), %r12
leal -0x4(%rbx), %ebp
leaq 0x20b40(%rip), %r15     # 0x2de70
pushq $0x1
popq %rax
movl %ebx, %ecx
movq %rcx, 0x8(%rsp)
movl %eax, %r13d
movq %rbx, 0x10(%rsp)
cmpl $0x0, (%r15)
je 0xd4dd
cmpl $0x6, %ebx
ja 0xd398
movq 0x8(%rsp), %rax
leaq 0x1095b(%rip), %rcx     # 0x1dcb8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
pushq $0x1
popq %rax
movl %eax, %r14d
jmp 0xd395
pushq $0x1
popq %rax
movl %eax, %r14d
jmp 0xd392
incl 0x4(%r15)
movq %r15, %rdi
callq 0x9aa7
pushq $0x1
jmp 0xd394
decl 0x4(%r15)
movq %r15, %rdi
callq 0x9aa7
pushq $-0x1
popq %rax
movl %eax, %r13d
movl %r14d, %ebx
movl (%r15), %edi
movl 0x4(%r15), %esi
movl 0x8(%r15), %edx
callq *%r12
leal -0x1(%rbx), %ecx
testl %eax, %eax
je 0xd3b4
testl %ecx, %ecx
je 0xd3df
testl %eax, %eax
cmovnel %ecx, %ebx
addl %r13d, 0x4(%r15)
movq %r15, %rdi
callq 0x9aa7
cmpl $0x2, %ebp
ja 0xd39b
testl %r13d, %r13d
leal 0x1(%r13,%r13), %eax
leal -0x1(%r13,%r13), %ecx
cmovgl %eax, %ecx
subl %ecx, %r13d
jmp 0xd39b
addq $0xc, %r15
movq 0x10(%rsp), %rbx
jmp 0xd342
leal 0x6(%r15), %eax
movl %eax, 0x10(%rsp)
leal 0x7(%r15), %eax
movl %eax, 0x8(%rsp)
leaq 0x20a6c(%rip), %r12     # 0x2de70
movl %ebx, %ebp
leaq 0x1088b(%rip), %r13     # 0x1dc98
movl (%r12), %edi
testl %edi, %edi
je 0xd4dd
movl 0x4(%r12), %esi
movl 0x8(%r12), %edx
callq 0x9d79
cmpl $0x7, %ebx
ja 0xd4ee
movslq (%r13,%rbp,4), %rcx
addq %r13, %rcx
jmpq *%rcx
movl 0x8(%rsp), %ecx
subl %eax, %ecx
movl %ecx, %eax
cltd
pushq $0x7
popq %rcx
idivl %ecx
movl 0x4(%r12), %eax
addl %edx, %eax
addl $-0x7, %eax
imull $-0x7, %r14d, %ecx
addl %ecx, %eax
addl $0x7, %eax
jmp 0xd4a3
cmpl %eax, %r15d
jne 0xd43b
movl 0x4(%r12), %eax
jmp 0xd453
cmpl %eax, %r15d
je 0xd4a8
orl $-0x1, 0x8(%r12)
jmp 0xd4a8
cmpl %eax, %r15d
jne 0xd483
movl 0x4(%r12), %eax
jmp 0xd49a
movl 0x10(%rsp), %ecx
subl %eax, %ecx
movl %ecx, %eax
cltd
pushq $0x7
popq %rcx
idivl %ecx
movl 0x4(%r12), %eax
addl %edx, %eax
incl %eax
imull $0x7, %r14d, %ecx
addl %ecx, %eax
addl $-0x7, %eax
movl %eax, 0x4(%r12)
movq %r12, %rdi
callq 0x9aa7
addq $0xc, %r12
jmp 0xd40d
movl %r15d, %r14d
subl %eax, %r14d
leal 0x7(%r14), %eax
cmpl $-0x3, %r14d
cmovgel %r14d, %eax
leal -0x7(%r14), %ecx
cmpl $0x4, %r14d
cmovgel %ecx, %eax
addl %eax, 0x4(%r12)
jmp 0xd4a8
xorl %eax, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x2
popq %rax
jmp 0xd4df
nop