int fix_labels(void) { struct section *s = NULL; struct label *l, *m; /* fix labels' addresses */ l = labels_first; while (l != NULL) { if (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_SYMBOL || l->status == LABEL_STATUS_BREAKPOINT) { if (l->section_status == ON) { s = sec_first; while (s != NULL) { if (s->id == l->section) { l->bank = s->bank; l->address += s->address; l->rom_address = l->address + bankaddress[l->bank]; if (s->status != SECTION_STATUS_ABSOLUTE) l->address += slots[l->slot].address; break; } s = s->next; } } else { l->rom_address = l->address + bankaddress[l->bank]; l->address += slots[l->slot].address; } } l = l->next; } /* check out if a label exists more than once in a different place */ l = labels_first; while (l != NULL) { if (is_label_anonymous(l->name) == FAILED && (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_DEFINE)) { m = l->next; while (m != NULL) { if (strcmp(m->name, l->name) == 0) { if (l->address != m->address && !(m->name[0] == '*' || m->name[0] == '_')) { if (l->status == LABEL_STATUS_DEFINE) fprintf(stderr, "%s: FIX_LABELS: Definition \"%s\" was defined more than once.\n", get_file_name(l->file_id), l->name); else fprintf(stderr, "%s:%s:%d: FIX_LABELS: Label \"%s\" was defined more than once.\n", get_file_name(l->file_id), get_source_file_name(l->file_id, l->file_id_source), l->linenumber, l->name); return FAILED; } } m = m->next; } } l = l->next; } return SUCCEEDED; }
int pass_3(void) { struct section_def *s; struct label_def *l; struct block *b; FILE *f_in; int bank = 0, slot = 0, add = 0, file_name_id = 0, inz, line_number = 0, o, add_old = 0; #ifdef W65816 int base = 0x00; #endif char c; s = NULL; if (verbose_mode == ON) printf("Internal pass 1...\n"); if ((f_in = fopen(gba_tmp_name, "rb")) == NULL) { fprintf(stderr, "INTERNAL_PASS_1: Error opening file \"%s\".\n", gba_tmp_name); return FAILED; } /* first loop */ o = 0; if (output_format == OUTPUT_OBJECT) { while (o == 0 && fread(&c, 1, 1, f_in) != 0) { switch (c) { case ' ': case 'E': continue; case 'P': add_old = add; continue; case 'p': add = add_old; continue; case 'x': fscanf(f_in, "%d %*d ", &inz); if (section_status == ON) { add += inz; continue; } fprintf(stderr, "INTERNAL_PASS_1: .ORG needs to be set before any code/data can be accepted.\n"); return FAILED; case 'd': if (section_status == ON) { fscanf(f_in, "%*s "); add++; continue; } fprintf(stderr, "INTERNAL_PASS_1: .ORG needs to be set before any code/data can be accepted.\n"); return FAILED; case 'y': if (section_status == ON) { fscanf(f_in, "%*d "); add += 2; continue; } fprintf(stderr, "INTERNAL_PASS_1: .ORG needs to be set before any code/data can be accepted.\n"); return FAILED; #ifdef W65816 case 'b': fscanf(f_in, "%d ", &base); continue; #endif case 'f': fscanf(f_in, "%d ", &file_name_id); continue; case 'B': fscanf(f_in, "%d %d ", &bank, &slot); continue; case 'k': fscanf(f_in, "%d ", &line_number); continue; case 'g': b = malloc(sizeof(struct block)); if (b == NULL) { fscanf(f_in, "%64s ", tmp); fprintf(stderr, "%s:%d INTERNAL_PASS_1: Out of memory while trying to allocate room for block \"%s\".\n", get_file_name(file_name_id), line_number, tmp); return FAILED; } b->next = blocks; blocks = b; fscanf(f_in, "%64s ", b->name); b->address = add; continue; case 'G': b = blocks; blocks = blocks->next; fprintf(stderr, "INTERNAL_PASS_1: Block \"%s\" is %d bytes.\n", b->name, add - b->address); free(b); continue; case 'Z': case 'Y': case 'L': l = malloc(sizeof(struct label_def)); if (l == NULL) { fscanf(f_in, "%64s ", tmp); fprintf(stderr, "%s:%d INTERNAL_PASS_1: Out of memory while trying to allocate room for label \"%s\".\n", get_file_name(file_name_id), line_number, tmp); return FAILED; } if (c == 'Y') l->symbol = 1; else if (c == 'L') l->symbol = 0; else l->symbol = 2; if (c == 'Z') l->label[0] = 0; else fscanf(f_in, "%64s ", l->label); l->next = NULL; l->section_status = ON; l->filename_id = file_name_id; l->linenumber = line_number; l->alive = ON; l->section_id = s->id; /* section labels get a relative address */ l->address = add; l->bank = s->bank; l->slot = s->slot; #ifdef W65816 l->base = base; #endif if (c == 'Z' || is_label_anonymous(l->label) == SUCCEEDED || strcmp(l->label, "__") == 0) { if (labels != NULL) { label_last->next = l; label_last = l; } else { labels = l; label_last = l; } continue; } label_next = labels; while (label_next != NULL) { if (strcmp(l->label, label_next->label) == 0) { if ((l->label[0] != '_') || /* both are not local labels */ (section_status == OFF && label_next->section_status == OFF) || (section_status == ON && label_next->section_status == ON && label_next->section_id == l->section_id)) { fprintf(stderr, "%s:%d: INTERNAL_PASS_1: Label \"%s\" was defined for the second time.\n", get_file_name(file_name_id), line_number, l->label); return FAILED; } } label_next = label_next->next; } if (labels != NULL) { label_last->next = l; label_last = l; } else { labels = l; label_last = l; } continue; case 'S': fscanf(f_in, "%d ", &inz); add_old = add; s = sections_first; while (s->id != inz) s = s->next; /* a RAMSECTION? */ if (s->status == SECTION_STATUS_RAM) { s->address = 0; s->listfile_items = 1; s->listfile_ints = NULL; s->listfile_cmds = NULL; add = 0; section_status = ON; continue; } fprintf(stderr, "INTERNAL_PASS_1: .ORG needs to be set before any code/data can be accepted.\n"); return FAILED; case 's': s->size = add - s->address; /* discard an empty section? */ if (s->size == 0) { fprintf(stderr, "INTERNAL_PASS_1: %s: Discarding an empty section \"%s\".\n", get_file_name(file_name_id), s->name); s->alive = OFF; /* discard all labels which belong to this section */ l = labels; while (l != NULL) { if (l->section_status == ON && l->section_id == s->id) l->alive = OFF; l = l->next; } } if (s->advance_org == NO) add = add_old; section_status = OFF; s = NULL; continue; case 'O': fscanf(f_in, "%d ", &add); o++; continue; default: fprintf(stderr, "INTERNAL_PASS_1: .ORG needs to be set before any code/data can be accepted.\n"); return FAILED; } } } else { while (o == 0 && fread(&c, 1, 1, f_in) != 0) { switch (c) { case ' ': case 'E': continue; case 'f': fscanf(f_in, "%d ", &file_name_id); continue; case 'S': fscanf(f_in, "%d ", &inz); add_old = add; s = sections_first; while (s->id != inz) s = s->next; if (s->status == SECTION_STATUS_FREE) add = 0; s->address = add; s->bank = bank; s->slot = slot; s->listfile_items = 1; s->listfile_ints = NULL; s->listfile_cmds = NULL; section_status = ON; o++; continue; default: fprintf(stderr, "INTERNAL_PASS_1: A section must be open before any code/data can be accepted.\n"); return FAILED; } } } /* second (major) loop */ while (fread(&c, 1, 1, f_in) != 0) { switch (c) { case ' ': case 'E': continue; case 'P': add_old = add; continue; case 'p': add = add_old; continue; case 'A': case 'S': if (c == 'A') fscanf(f_in, "%d %*d", &inz); else fscanf(f_in, "%d ", &inz); add_old = add; s = sections_first; while (s->id != inz) s = s->next; if (s->status == SECTION_STATUS_FREE || s->status == SECTION_STATUS_RAM) add = 0; if (s->status != SECTION_STATUS_RAM) { s->bank = bank; s->slot = slot; } s->address = add; s->listfile_items = 1; s->listfile_ints = NULL; s->listfile_cmds = NULL; section_status = ON; continue; case 's': s->size = add - s->address; /* discard an empty section? */ if (s->size == 0) { fprintf(stderr, "DISCARD: %s: Discarding an empty section \"%s\".\n", get_file_name(file_name_id), s->name); s->alive = OFF; /* discard all labels which belong to this section */ l = labels; while (l != NULL) { if (l->section_status == ON && l->section_id == s->id) l->alive = OFF; l = l->next; } } /* some sections don't affect the ORG outside of them */ if (s->advance_org == NO) add = add_old; section_status = OFF; s = NULL; continue; case 'x': fscanf(f_in, "%d %*d ", &inz); add += inz; continue; case 'X': fscanf(f_in, "%d %*d ", &inz); add += inz << 1; continue; #ifdef W65816 case 'z': case 'q': fscanf(f_in, "%*s "); add += 3; continue; case 'T': fscanf(f_in, "%*d "); add += 3; continue; case 'b': fscanf(f_in, "%d ", &base); continue; #endif case 'R': case 'Q': case 'd': case 'c': fscanf(f_in, "%*s "); add++; continue; #ifdef W65816 case 'M': #endif case 'r': fscanf(f_in, "%*s "); add += 2; continue; case 'y': case 'C': fscanf(f_in, "%*d "); add += 2; continue; case 'D': fscanf(f_in, "%*d %*d %*d %d ", &inz); add += inz; continue; case 'O': fscanf(f_in, "%d ", &add); continue; case 'B': fscanf(f_in, "%d %d ", &bank, &slot); continue; case 'g': b = malloc(sizeof(struct block)); if (b == NULL) { fscanf(f_in, "%64s ", tmp); fprintf(stderr, "%s:%d INTERNAL_PASS_1: Out of memory while trying to allocate room for block \"%s\".\n", get_file_name(file_name_id), line_number, tmp); return FAILED; } b->next = blocks; blocks = b; fscanf(f_in, "%64s ", b->name); b->address = add; continue; case 'G': b = blocks; blocks = blocks->next; fprintf(stderr, "INTERNAL_PASS_1: Block \"%s\" is %d bytes.\n", b->name, add - b->address); free(b); continue; case 'Z': case 'Y': case 'L': l = malloc(sizeof(struct label_def)); if (l == NULL) { fscanf(f_in, "%64s ", tmp); fprintf(stderr, "%s:%d INTERNAL_PASS_1: Out of memory while trying to allocate room for label \"%s\".\n", get_file_name(file_name_id), line_number, tmp); return FAILED; } if (c == 'Y') l->symbol = 1; else if (c == 'L') l->symbol = 0; else l->symbol = 2; if (c == 'Z') l->label[0] = 0; else fscanf(f_in, "%64s ", l->label); l->next = NULL; l->section_status = section_status; l->filename_id = file_name_id; l->linenumber = line_number; l->alive = ON; if (section_status == ON) { l->section_id = s->id; /* section labels get a relative address */ l->address = add - s->address; l->bank = s->bank; l->slot = s->slot; } else { l->section_id = 0; l->address = add; l->bank = bank; l->slot = slot; } #ifdef W65816 l->base = base; #endif if (c == 'Z' || is_label_anonymous(l->label) == SUCCEEDED || strcmp(l->label, "__") == 0) { if (labels != NULL) { label_last->next = l; label_last = l; } else { labels = l; label_last = l; } continue; } label_next = labels; while (label_next != NULL) { if (strcmp(l->label, label_next->label) == 0) { if ((l->label[0] != '_') || /* both are not local labels */ (section_status == OFF && label_next->section_status == OFF) || (section_status == ON && label_next->section_status == ON && label_next->section_id == l->section_id)) { fprintf(stderr, "%s:%d: INTERNAL_PASS_1: Label \"%s\" was defined for the second time.\n", get_file_name(file_name_id), line_number, l->label); return FAILED; } } label_next = label_next->next; } if (labels != NULL) { label_last->next = l; label_last = l; } else { labels = l; label_last = l; } continue; case 'f': fscanf(f_in, "%d ", &file_name_id); if (s != NULL) s->listfile_items++; continue; case 'k': fscanf(f_in, "%d ", &line_number); if (s != NULL) s->listfile_items++; continue; default: fprintf(stderr, "%s: INTERNAL_PASS_1: Unknown internal symbol \"%c\".\n", get_file_name(file_name_id), c); return FAILED; } } fclose(f_in); return SUCCEEDED; }
int fix_references(void) { struct reference *r; struct section *s = NULL; struct label *l, lt; int i, x; section_overwrite = OFF; /* insert references */ r = reference_first; while (r != NULL) { x = r->address; /* search for the section of the reference and fix the address */ if (r->section_status == ON) { s = sec_first; while (s != NULL) { if (s->id == r->section) { r->bank = s->bank; x += s->address; r->address += s->address; break; } s = s->next; } /* reference is inside a discarded section? */ if (s != NULL && s->alive == NO) { r = r->next; continue; } if (s == NULL) { if (write_bank_header_references(r) == FAILED) return FAILED; r = r->next; continue; } } if (!(r->section_status == ON && s->status == SECTION_STATUS_ABSOLUTE)) { x += bankaddress[r->bank]; r->address += slots[r->slot].address; } /* find the destination */ l = labels_first; /* request for bank number? */ if (r->name[0] == ':') { if (is_label_anonymous(&r->name[1]) == SUCCEEDED) { l = get_closest_anonymous_label(&r->name[1], x, r->file_id, l, r->section_status, r->section); } else if (strcmp(&r->name[1], "CADDR") == 0 || strcmp(&r->name[1], "caddr") == 0) { lt.status = LABEL_STATUS_LABEL; strcpy(lt.name, &r->name[1]); lt.address = r->address; lt.bank = r->bank; lt.section_status = OFF; l = < } else { while (l != NULL) { if (strcmp(l->name, &r->name[1]) == 0 && l->status != LABEL_STATUS_SYMBOL && l->status != LABEL_STATUS_BREAKPOINT) break; l = l->next; } } if (l == NULL) { fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Bank number request for an unknown label \"%s\".\n", get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, &r->name[1]); return FAILED; } if (cpu_65816 != 0) i = get_snes_pc_bank(l) >> 16; else i = l->bank; memory_file_id = r->file_id; memory_file_id_source = r->file_id_source; memory_line_number = r->linenumber; /* direct 16bit */ if (r->type == REFERENCE_TYPE_DIRECT_16BIT || r->type == REFERENCE_TYPE_RELATIVE_16BIT) { mem_insert_ref(x, i & 0xFF); mem_insert_ref(x + 1, (i >> 8) & 0xFF); } /* direct / relative 8bit with a definition */ else if (l->status == LABEL_STATUS_DEFINE) {
int discard_iteration(void) { struct reference *r; struct stackitem *si; struct section *s, *ss; struct label *l; struct stack *st; int i; /* check section names for special characters '!', and check if the section is of proper type */ s = sec_first; while (s != NULL) { if (s->name[0] == '!' || !(s->status == SECTION_STATUS_FREE || s->status == SECTION_STATUS_SEMIFREE || s->status == SECTION_STATUS_SEMISUBFREE)) { s->referenced++; s->alive = YES; } s = s->next; } /* loop through references */ r = reference_first; while (r != NULL) { /* references to local labels don't count */ if (r->name[0] == '_' || is_label_anonymous(r->name) == SUCCEEDED) { r = r->next; continue; } s = NULL; if (r->section_status != 0) { s = sec_first; while (s != NULL) { if (s->id == r->section) break; s = s->next; } } find_label(r->name, s, &l); if (l != NULL && l->section_status == ON) { s = l->section_struct; if (s == NULL) fprintf(stderr, "DISCARD_ITERATION: Internal error!\n"); if (r->section_status == OFF) s->referenced++; else if (r->section != s->id) { ss = sec_first; while (ss->id != r->section) ss = ss->next; if (ss->alive == YES) s->referenced++; } } r = r->next; } /* loop through computations */ st = stacks_first; while (st != NULL) { ss = NULL; if (st->section_status != 0) { ss = sec_first; while (ss != NULL) { if (ss->id == st->section) break; ss = ss->next; } } si = st->stack; i = 0; while (i != st->stacksize) { if (si->type == STACK_ITEM_TYPE_STRING && is_label_anonymous(si->string) == FAILED) { find_label(si->string, ss, &l); if (l != NULL && l->section_struct != NULL) { s = l->section_struct; if (st->section_status == OFF) s->referenced++; else if (st->section != s->id) { if (ss->alive == YES) s->referenced++; } } } si++; i++; } st = st->next; } return SUCCEEDED; }