// File: /workspace/github_c_makefile_star2_O1/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 0xcd57
cmpl $-0x1, %eax
je 0xe0f1
movl %eax, %ebx
addq $0x8, %rbp
movq %rbp, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0xd53d
testl %eax, %eax
jne 0xe0f6
leal -0x7(%r15), %ecx
cmpl $0xb, %ecx
jae 0xdf9a
xorl %eax, %eax
cmpl $0x0, 0x1ffee(%rip)     # 0x2de80
je 0xe0f6
movl %ecx, %eax
leaq 0x1a34f(%rip), %rcx     # 0x281f0
movq (%rcx,%rax,8), %r12
leal -0x4(%rbx), %ebp
movl $0x1, %r13d
leaq 0x1ffcb(%rip), %r15     # 0x2de80
movl %ebx, %eax
movq %rax, 0x8(%rsp)
movq %rbx, 0x10(%rsp)
cmpl $0x6, %ebx
ja 0xdf17
movq 0x8(%rsp), %rax
leaq 0x10dc2(%rip), %rcx     # 0x1ec94
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x1, %r14d
jmp 0xdefd
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movl $0x1, %r14d
jmp 0xdf17
incl 0x4(%r15)
movq %r15, %rdi
callq 0xa1b1
movl $0x1, %r13d
jmp 0xdf17
decl 0x4(%r15)
movq %r15, %rdi
callq 0xa1b1
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movl (%r15), %edi
movl 0x4(%r15), %esi
movl 0x8(%r15), %edx
callq *%r12
testl %eax, %eax
sete %cl
movl %r14d, %ebx
decl %ebx
setne %dl
orb %cl, %dl
cmpb $0x1, %dl
jne 0xdf7f
testl %eax, %eax
cmovel %r14d, %ebx
addl %r13d, 0x4(%r15)
movq %r15, %rdi
callq 0xa1b1
cmpl $0x2, %ebp
ja 0xdf63
testl %r13d, %r13d
leal 0x1(%r13,%r13), %eax
leal -0x1(%r13,%r13), %ecx
cmovgl %eax, %ecx
subl %ecx, %r13d
movl (%r15), %edi
movl 0x4(%r15), %esi
movl 0x8(%r15), %edx
callq *%r12
leal -0x1(%rbx), %ecx
testl %eax, %eax
cmovnel %ecx, %ebx
je 0xdf3f
testl %ecx, %ecx
jne 0xdf3f
cmpl $0x0, 0xc(%r15)
leaq 0xc(%r15), %r15
movq 0x10(%rsp), %rbx
jne 0xdec1
xorl %eax, %eax
jmp 0xe0f6
movl 0x1fee0(%rip), %edi     # 0x2de80
xorl %eax, %eax
testl %edi, %edi
je 0xe0f6
leal 0x6(%r15), %eax
movl %eax, 0x10(%rsp)
leal 0x7(%r15), %eax
movl %eax, 0x8(%rsp)
leaq 0x1febf(%rip), %r12     # 0x2de80
movl %ebx, %r13d
leaq 0x10ca9(%rip), %rbp     # 0x1ec74
movl 0x4(%r12), %esi
movl 0x8(%r12), %edx
callq 0xa53f
cmpl $0x7, %ebx
ja 0xe0f1
movslq (%rbp,%r13,4), %rcx
addq %rbp, %rcx
jmpq *%rcx
movl 0x8(%rsp), %ecx
subl %eax, %ecx
movslq %ecx, %rax
imulq $-0x6db6db6d, %rax, %rcx # imm = 0x92492493
shrq $0x20, %rcx
addl %eax, %ecx
movl %ecx, %edx
shrl $0x1f, %edx
sarl $0x2, %ecx
addl %edx, %ecx
leal (,%rcx,8), %edx
subl %edx, %ecx
addl %eax, %ecx
movl 0x4(%r12), %eax
addl %ecx, %eax
addl $-0x7, %eax
movl %eax, 0x4(%r12)
leal (,%r14,8), %eax
movl %r14d, %ecx
subl %eax, %ecx
movl 0x4(%r12), %eax
addl %ecx, %eax
addl $0x7, %eax
jmp 0xe0aa
cmpl %eax, %r15d
je 0xe027
jmp 0xdfed
cmpl %eax, %r15d
je 0xe0af
movl $0xffffffff, 0x8(%r12)  # imm = 0xFFFFFFFF
jmp 0xe0af
cmpl %eax, %r15d
je 0xe095
movl 0x10(%rsp), %ecx
subl %eax, %ecx
movslq %ecx, %rax
imulq $-0x6db6db6d, %rax, %rcx # imm = 0x92492493
shrq $0x20, %rcx
addl %eax, %ecx
movl %ecx, %edx
shrl $0x1f, %edx
sarl $0x2, %ecx
addl %edx, %ecx
leal (,%rcx,8), %edx
subl %edx, %ecx
addl %eax, %ecx
movl 0x4(%r12), %eax
addl %ecx, %eax
incl %eax
movl %eax, 0x4(%r12)
leal (,%r14,8), %eax
subl %r14d, %eax
movl 0x4(%r12), %ecx
addl %ecx, %eax
addl $-0x7, %eax
movl %eax, 0x4(%r12)
movq %r12, %rdi
callq 0xa1b1
movl 0xc(%r12), %edi
addq $0xc, %r12
testl %edi, %edi
jne 0xdfcb
jmp 0xdf93
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 0xe0af
movl $0x2, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)