// File: /workspace/github_c_makefile_star2_O2/simh[P]simtools/crossassemblers/macro11/mlb-rsx.c
// Function: mlb_open
MLB            *mlb_open(
    char *name,
    int allow_objlib)
{
    MLB            *mlb = memcheck(malloc(sizeof(MLB)));
    char           *buff;
    unsigned        entsize;
    unsigned        nr_entries;
    unsigned        start_block;
    int             i;

    mlb->directory = NULL;

    mlb->fp = fopen(name, "rb");
    if (mlb->fp == NULL) {
        mlb_close(mlb);
        return NULL;
    }

    buff = memcheck(malloc(060));      /* Size of MLB library header */

    if (fread(buff, 1, 060, mlb->fp) < 060) {
        fprintf(stderr, "error: can't read full header\n");
        mlb_close(mlb);
        free(buff);
        return NULL;
    }

    mlb->is_objlib = 0;
    if (allow_objlib && WORD(buff) == 01000) { /* Is it an object library? */
        mlb->is_objlib = 1;
    } else if (WORD(buff) != 01001) {  /* Is this really a macro library? */
        fprintf(stderr, "error: first word not correct value\n");
        mlb_close(mlb);                /* Nope. */
        return NULL;
    }

    entsize = buff[032];               /* The size of each macro directory
                                          entry */
    nr_entries = WORD(buff + 036);     /* The number of directory entries */
    start_block = WORD(buff + 034) - 1;/* The start RT-11 block of the
                                          directory */

    if (entsize < 8) {                 /* Is this really a macro library? */
        mlb_close(mlb);                /* Nope. */
        fprintf(stderr, "error: entsize too small: %d\n", entsize);
        return NULL;
    }

//    fprintf(stderr, "entsize=%d, nr_entries=%d, start_block=%d\n",
//            entsize, nr_entries, start_block);
    free(buff);                        /* Done with that header. */

    /* Allocate a buffer for the disk directory */
    buff = memcheck(malloc(nr_entries * entsize));
    fseek(mlb->fp, start_block * BLOCKSIZE, SEEK_SET);        /* Go to the directory */

    /* Read the disk directory */
    if (fread(buff, entsize, nr_entries, mlb->fp) < nr_entries) {
        mlb_close(mlb);                /* Sorry, read error. */
        free(buff);
        return NULL;
    }

    /* Shift occupied directory entries to the front of the array */
    {
        int             j;

        for (i = 0, j = nr_entries; i < j; i++) {
            char           *ent1,
                           *ent2;

            ent1 = buff + (i * entsize);
            /* Unused entries have 0177777 0177777 for the RAD50 name,
               which is not legal RAD50. */
            if (WORD(ent1) == 0177777 && WORD(ent1 + 2) == 0177777) {
                while (--j > i
                       && (ent2 = buff + (j * entsize), WORD(ent2) == 0177777 && WORD(ent2 + 2) == 0177777)) ;
                if (j <= i)
                    break;             /* All done. */
                memcpy(ent1, ent2, entsize);    /* Move used entry
                                                   into unused entry's
                                                   space */
                memset(ent2, 0377, entsize);    /* Mark entry unused */
            } else {
//            fprintf(stderr, "entry %d:  %02x%02x.%02x%02x\n",
//                    i, ent1[5] & 0xFF, ent1[4] & 0xFF, ent1[7] & 0xFF, ent1[6] & 0xFF);
            }
        }

        /* Now i contains the actual number of entries. */

        mlb->nentries = i;
//        fprintf(stderr, " mlb->nentries=%d\n",  mlb->nentries);

        /* Now, allocate my in-memory directory */
        mlb->directory = memcheck(malloc(sizeof(MLBENT) * mlb->nentries));
        memset(mlb->directory, 0, sizeof(MLBENT) * mlb->nentries);

        /* Build in-memory directory */
        for (j = 0; j < i; j++) {
            char            radname[16];
            char           *ent;

            ent = buff + (j * entsize);

            unrad50(WORD(ent), radname);
            unrad50(WORD(ent + 2), radname + 3);
            radname[6] = 0;

//            fprintf(stderr, "entry %d: \"%s\" %02x%02x.%02x%02x\n",
//                    j, radname,
//                    ent[5] & 0xFF, ent[4] & 0xFF, ent[7] & 0xFF, ent[6] & 0xFF);
            trim(radname);

            mlb->directory[j].label = memcheck(strdup(radname));
            mlb->directory[j].position = BYTEPOS(ent);
//            fprintf(stderr, "entry %d: \"%s\" bytepos=%d\n", j, mlb->directory[j].label, mlb->directory[j].position);
            mlb->directory[j].length = -1;
        }

        free(buff);
    }

    /* Done.  Return the struct that represents the opened MLB. */
    return mlb;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %esi, %ebp
movq %rdi, %r14
pushq $0x18
popq %rdi
callq 0x2230
movq %rax, %rdi
callq 0xcd2d
movq %rax, %rbx
andq $0x0, 0x8(%rax)
leaq 0x47ce(%rip), %rsi      # 0xfbb4
movq %r14, %rdi
callq 0x2270
movq %rax, (%rbx)
testq %rax, %rax
je 0xb6c1
pushq $0x30
popq %r15
movq %r15, %rdi
callq 0x2230
movq %rax, %rdi
callq 0xcd2d
movq %rax, %r14
movq (%rbx), %rcx
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %r15, %rdx
callq 0x20c0
cmpq $0x2f, %rax
jbe 0xb65d
andl $0x0, 0x14(%rbx)
testl %ebp, %ebp
setne %cl
movzwl (%r14), %eax
cmpw $0x200, %ax             # imm = 0x200
sete %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0xb450
movl $0x1, 0x14(%rbx)
jmp 0xb45a
cmpw $0x201, %ax             # imm = 0x201
jne 0xb6a5
movsbl 0x1a(%r14), %ebp
cmpl $0x7, %ebp
jbe 0xb67e
movzwl 0x1e(%r14), %r15d
movzwl 0x1c(%r14), %r12d
shll $0x9, %r12d
movq %r14, %rdi
callq 0x2050
movl %r15d, %edi
imull %ebp, %edi
callq 0x2230
movq %rax, %rdi
callq 0xcd2d
movq %rax, %r14
movq (%rbx), %rdi
addl $0xfffffe00, %r12d      # imm = 0xFFFFFE00
movq %r12, %rsi
xorl %edx, %edx
callq 0x2250
movl %ebp, %esi
movq (%rbx), %rcx
movq %r14, %rdi
movq %rsi, 0x8(%rsp)
movq %r15, %rdx
callq 0x20c0
cmpq %r15, %rax
jae 0xb4d7
movq %rbx, %rdi
callq 0xb6de
movq %r14, %rdi
callq 0x2050
jmp 0xb6c9
xorl %r12d, %r12d
movq %rbx, 0x20(%rsp)
movslq %r15d, %rax
cmpq %rax, %r12
jge 0xb55d
movl %r12d, %edi
imull %ebp, %edi
cmpw $-0x1, (%r14,%rdi)
jne 0xb558
addq %r14, %rdi
cmpw $-0x1, 0x2(%rdi)
jne 0xb558
movl %r15d, %ecx
decl %r15d
imull %ebp, %r15d
decq %rcx
movl %r15d, %eax
cmpq %r12, %rcx
jle 0xb55d
movq %rcx, %r15
movl %eax, %ecx
leaq (%r14,%rcx), %r13
cmpw $-0x1, (%r14,%rcx)
jne 0xb533
leaq -0x1(%r15), %rcx
subl %ebp, %eax
cmpw $-0x1, 0x2(%r13)
je 0xb50f
movq %r13, %rsi
movq 0x8(%rsp), %rbx
movq %rbx, %rdx
callq 0x2220
movq %r13, %rdi
movl $0xff, %esi
movq %rbx, %rdx
movq 0x20(%rsp), %rbx
callq 0x2140
incq %r12
jmp 0xb4df
movl %r12d, 0x10(%rbx)
movl %r12d, %eax
movq %rax, 0x8(%rsp)
imulq $0x18, %rax, %rdi
callq 0x2230
movq %rax, %rdi
callq 0xcd2d
movq %rax, 0x8(%rbx)
movq %rbx, %r13
movslq 0x10(%rbx), %rcx
imulq $0x18, %rcx, %rdx
xorl %ebx, %ebx
movq %rax, %rdi
xorl %esi, %esi
callq 0x2140
leaq 0x10(%rsp), %r12
cmpq 0x8(%rsp), %rbx
je 0xb653
movl %ebx, %r15d
imull %ebp, %r15d
movzwl (%r14,%r15), %edi
movq %r12, %rsi
callq 0xd03e
movzwl 0x2(%r14,%r15), %edi
leaq 0x13(%rsp), %rsi
callq 0xd03e
movb $0x0, 0x16(%rsp)
movq %r12, %rdi
callq 0x20e0
leaq 0xf(%rsp), %rcx
addq %rcx, %rax
cmpq %r12, %rax
jb 0xb5f0
cmpb $0x20, (%rax)
jne 0xb5f0
movb $0x0, (%rax)
decq %rax
jmp 0xb5de
movq %r12, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0xcd2d
movq 0x8(%r13), %rcx
imulq $0x18, %rbx, %rdx
movq %rax, (%rcx,%rdx)
movzbl 0x4(%r14,%r15), %eax
movzbl 0x5(%r14,%r15), %esi
andl $0x7f, %esi
shll $0x8, %esi
orl %eax, %esi
shll $0x9, %esi
movzbl 0x6(%r14,%r15), %eax
movzbl 0x7(%r14,%r15), %edi
andl $0x1, %edi
shll $0x8, %edi
orl %eax, %edi
leal (%rsi,%rdi), %eax
addl $0xfffffe00, %eax       # imm = 0xFFFFFE00
cltq
movq %rax, 0x8(%rcx,%rdx)
orl $-0x1, 0x10(%rcx,%rdx)
incq %rbx
jmp 0xb59a
movq %r14, %rdi
callq 0x2050
jmp 0xb6cc
movq 0x9994(%rip), %rax      # 0x14ff8
movq (%rax), %rcx
leaq 0x4549(%rip), %rdi      # 0xfbb7
pushq $0x1e
popq %rsi
pushq $0x1
popq %rdx
callq 0x22d0
jmp 0xb4c2
movq %rbx, %rdi
callq 0xb6de
movq 0x996b(%rip), %rax      # 0x14ff8
movq (%rax), %rdi
leaq 0x4564(%rip), %rsi      # 0xfbfb
xorl %r13d, %r13d
movl %ebp, %edx
xorl %eax, %eax
callq 0x21e0
jmp 0xb6cc
movq 0x994c(%rip), %rax      # 0x14ff8
movq (%rax), %rcx
leaq 0x4520(%rip), %rdi      # 0xfbd6
pushq $0x24
popq %rsi
pushq $0x1
popq %rdx
callq 0x22d0
movq %rbx, %rdi
callq 0xb6de
xorl %r13d, %r13d
movq %r13, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq