diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index d69a81d01..a8bec97e2 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -70,26 +70,10 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "strpool.h" #include "type.h" -#define Xgroup(X)\ -typedef struct {\ - qfo_##X##_t *X##s;\ - int num_##X##s;\ - int max_##X##s;\ -} X##group_t; - -Xgroup(def) // defgroup_t -Xgroup(reloc) // relocgroup_t -Xgroup(func) // funcgroup_t - -typedef struct path_s { - struct path_s *next; - const char *path; -} path_t; - -typedef union defref_s { - int def; - union defref_s *next; -} defref_t; +static void def_error (qfo_def_t *def, const char *fmt, ...) + __attribute__ ((used, format (printf, 2, 3))); +static void def_warning (qfo_def_t *def, const char *fmt, ...) + __attribute__ ((used, format (printf, 2, 3))); typedef struct builtin_sym_s { const char *name; @@ -97,7 +81,7 @@ typedef struct builtin_sym_s { unsigned flags; } builtin_sym_t; -static builtin_sym_t builtin_symbols[] = { +static builtin_sym_t builtin_symbols[] __attribute__ ((used)) = { {".zero", &type_zero, QFOD_NOSAVE}, {".return", &type_param, QFOD_NOSAVE}, {".param_0", &type_param, QFOD_NOSAVE}, @@ -110,631 +94,199 @@ static builtin_sym_t builtin_symbols[] = { {".param_7", &type_param, QFOD_NOSAVE}, }; -static defref_t *free_defrefs; +static qfo_t *work; +static strpool_t *work_strings; +static codespace_t *work_code; +static defspace_t *work_near_data; +static defspace_t *work_far_data; +static defspace_t *work_entity_data; +static defspace_t *work_type_data; -static hashtab_t *extern_defs; -static hashtab_t *defined_defs; -static hashtab_t *field_defs; +/** Add a string to the working qfo string pool. -static codespace_t *code; -static defspace_t *data; -static defspace_t *far_data; -static defspace_t *entity; -static strpool_t *strings; -static strpool_t *type_strings; -static relocgroup_t relocs, final_relocs; -static defgroup_t global_defs, local_defs, fields, defs; -static funcgroup_t funcs; -static struct { - pr_lineno_t *lines; - int num_lines; - int max_lines; -} lines; -static int code_base; -static int data_base; -static int far_data_base; -static int entity_base; -static int reloc_base; -static int func_base; -static int line_base; + If the string is already in the string pool, the already existing string + index will be returned instead of adding a second copy of the string. -static path_t *path_head; -static path_t **path_tail = &path_head; + The strings space in the working qfo is kept up to date. -#define DATA(x) (data->data + (x)) -#define STRING(x) (strings->strings + (x)) -#define TYPE_STRING(x) (type_strings->strings + (x)) - -#define Xgroup_add(X)\ -static void \ -X##group_add_##X##s (X##group_t *X##group, qfo_##X##_t *X##s, int num_##X##s)\ -{\ - if (X##group->num_##X##s + num_##X##s > X##group->max_##X##s) {\ - X##group->max_##X##s = RUP (X##group->num_##X##s + num_##X##s, 16384);\ - X##group->X##s = realloc (X##group->X##s,\ - X##group->max_##X##s * sizeof (qfo_##X##_t));\ - }\ - memcpy (X##group->X##s + X##group->num_##X##s, X##s,\ - num_##X##s * sizeof (qfo_##X##_t));\ - X##group->num_##X##s += num_##X##s;\ -} - -Xgroup_add(def); // defgroup_add_defs -Xgroup_add(reloc); // relocgroup_add_relocs -Xgroup_add(func); // funcgroup_add_funcs - -static void def_error (qfo_def_t *def, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -//static void def_warning (qfo_def_t *def, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); - -static defref_t * -get_defref (qfo_def_t *def, defgroup_t *defgroup) -{ - defref_t *defref; - - ALLOC (16384, defref_t, defrefs, defref); - defref->def = def - defgroup->defs; - return defref; -} - -static qfo_def_t * -deref_def (defref_t *defref, defgroup_t *defgroup) -{ - return defgroup->defs + defref->def; -} - -static const char * -defs_get_key (void *_defref, void *_defgroup) -{ - defref_t *defref = (defref_t *) _defref; - defgroup_t *defgroup = (defgroup_t *) _defgroup; - qfo_def_t *def = deref_def (defref, defgroup); - - return STRING (def->name); -} - -static void -add_strings (qfo_t *qfo) -{ -// int i; - -// for (i = 0; i < qfo->strings_size; i += strlen (qfo->strings + i) + 1) -// strpool_addstr (strings, qfo->strings + i); -} - -static void -add_relocs (qfo_t *qfo) -{ - int i; - - relocgroup_add_relocs (&relocs, qfo->relocs, qfo->num_relocs); - for (i = reloc_base; i < relocs.num_relocs; i++) { - qfo_reloc_t *reloc = relocs.relocs + i; - switch ((reloc_type)reloc->type) { - case rel_none: - break; - case rel_op_a_def: - case rel_op_b_def: - case rel_op_c_def: - case rel_op_a_def_ofs: - case rel_op_b_def_ofs: - case rel_op_c_def_ofs: - reloc->offset += code_base; - break; - case rel_op_a_op: - case rel_op_b_op: - case rel_op_c_op: - // these are relative and fixed up before the .qfo is written - break; - case rel_def_op: - reloc->offset += data_base; - reloc->def += code_base; - break; - case rel_def_func: - reloc->offset += data_base; - reloc->def += func_base; - break; - case rel_def_def: - case rel_def_def_ofs: - reloc->offset += data_base; - break; - case rel_def_string: - reloc->offset += data_base; -// DATA (reloc->offset)->string_var = -// strpool_addstr (strings, -// qfo->strings + DATA (reloc->offset)->string_var); - break; - case rel_def_field: - case rel_def_field_ofs: - //FIXME more? - reloc->offset += data_base; - break; - } - } -} - -//static void -//linker_type_mismatch (qfo_def_t *def, qfo_def_t *d) -//{ -// def_error (def, "type mismatch for `%s' `%s'", -// STRING (def->name), -// TYPE_STRING (def->full_type)); -// def_error (d, "previous definition `%s'", TYPE_STRING (d->full_type)); -//} - -static void -process_def (qfo_def_t *def) -{ - defref_t *_d; - qfo_def_t *d; - - if (def->flags & QFOD_EXTERNAL) { - if (!def->num_relocs) - return; - if ((_d = Hash_Find (defined_defs, STRING (def->name)))) { - d = deref_def (_d, &global_defs); -// if (d->full_type != def->full_type) { -// linker_type_mismatch (def, d); -// return; -// } - def->offset = d->offset; - def->flags = d->flags; - Hash_Add (defined_defs, get_defref (def, &global_defs)); - } else { - Hash_Add (extern_defs, get_defref (def, &global_defs)); - } - } else if (def->flags & QFOD_GLOBAL) { - if ((_d = Hash_Find (defined_defs, STRING (def->name)))) { - d = deref_def (_d, &global_defs); - if (d->flags & QFOD_SYSTEM) { -// int i, size; - -// if (d->full_type != def->full_type) { -// linker_type_mismatch (def, d); -// return; -// } - d->flags &= ~QFOD_SYSTEM; - d->flags |= def->flags & (QFOD_INITIALIZED | QFOD_CONSTANT); -// size = type_size (parse_type (TYPE_STRING (d->full_type))); -// memcpy (DATA (d->offset), DATA (def->offset), -// size * sizeof (pr_type_t)); -// for (i = 0; i < relocs.num_relocs; i++) { -// qfo_reloc_t *reloc = relocs.relocs + i; -// if (reloc->type >= rel_def_def -// && reloc->type <= rel_def_field) -// if (reloc->offset == def->offset) -// reloc->offset = d->offset; -// } - def->offset = d->offset; - def->flags = d->flags; - } else { - def_error (def, "%s redefined", STRING (def->name)); - def_error (d, "previous definition"); - } - } - while ((_d = Hash_Del (extern_defs, STRING (def->name)))) { - Hash_Add (defined_defs, _d); - d = deref_def (_d, &global_defs); -// if (d->full_type != def->full_type) { -// linker_type_mismatch (def, d); -// continue; -// } - d->offset = def->offset; - d->flags = def->flags; - } - Hash_Add (defined_defs, get_defref (def, &global_defs)); - } -} - -static void -process_field (qfo_def_t *def) -{ - defref_t *_d; - qfo_def_t *field_def; - pr_type_t *var = DATA (def->offset); - - if (strcmp (STRING (def->name), ".imm")) { //FIXME better test - if ((_d = Hash_Find (field_defs, STRING (def->name)))) { - field_def = deref_def (_d, &fields); - def_error (def, "%s redefined", STRING (def->name)); - def_error (field_def, "previous definition"); - } - } - defgroup_add_defs (&fields, def, 1); - field_def = fields.defs + fields.num_defs - 1; - field_def->offset = var->integer_var + entity_base; - Hash_Add (field_defs, get_defref (field_def, &fields)); -} - -static void -fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num) -{ - pr_int_t i; - qfo_reloc_t *reloc; -// qfo_func_t *func; -// const char *full_type = QFO_TYPESTR (qfo, def->full_type); -// const char *name = QFO_GETSTR (qfo, def->name); - -// def->full_type = strpool_addstr (type_strings, full_type); -// def->name = strpool_addstr (strings, name); - - def->relocs += reloc_base; - for (i = 0, reloc = relocs.relocs + def->relocs; - i < def->num_relocs; - i++, reloc++) - reloc->def = def_num; - -// def->file = strpool_addstr (strings, qfo->strings + def->file); - - if ((def->flags & (QFOD_LOCAL | QFOD_ABSOLUTE))) - return; - if (!(def->flags & QFOD_EXTERNAL)) { - def->offset += data_base; -// if (def->flags & QFOD_INITIALIZED) { -// pr_type_t *var = DATA (def->offset); -// switch (def->basic_type) { -// case ev_func: -// if (var->func_var) { -// func = funcs.funcs + var->func_var - 1; -// func->def = def_num; -// } -// break; -// case ev_field: -// process_field (def); -// break; -// default: -// break; -// } -// } - } - process_def (def); -} - -/* Transfer global defs from the object file. Local defs are skipped because - they will be handled by add_funcs. + \param str The string to add. + \return The string offset in the working qfo string pool. */ -static void -add_defs (qfo_t *qfo) +static string_t +add_string (const char *str) { - qfo_def_t *s, *e; + string_t new; + new = strpool_addstr (work_strings, str); + work->spaces[qfo_strings_space].d.strings = work_strings->strings; + work->spaces[qfo_strings_space].data_size = work_strings->size; + return new; +} - for (s = e = qfo->defs; s - qfo->defs < qfo->num_defs; s = e) { - int def_num = global_defs.num_defs; - qfo_def_t *d; - // find the end of the current chunk of global defs - while (e - qfo->defs < qfo->num_defs && !(e->flags & QFOD_LOCAL)) - e++; - defgroup_add_defs (&global_defs, s, e - s); - for (d = global_defs.defs + def_num; def_num < global_defs.num_defs; - d++, def_num++) - fixup_def (qfo, d, def_num); - // find the beginning of the next chunk of global defs - while (e - qfo->defs < qfo->num_defs && (e->flags & QFOD_LOCAL)) - e++; +static void +add_qfo_strings (qfo_mspace_t *strings) +{ + const char *str = strings->d.strings; + + while (str - strings->d.strings < strings->data_size) { + add_string (str); + while (str - strings->d.strings < strings->data_size && *str) + str++; + str++; // advance past the terminating nul } } static void -add_funcs (qfo_t *qfo) +add_code (qfo_mspace_t *code) +{ + codespace_addcode (work_code, code->d.code, code->data_size); + work->spaces[qfo_code_space].d.code = work_code->code; + work->spaces[qfo_code_space].data_size = work_code->size; +} + +static void +add_data (int space, qfo_mspace_t *data) +{ + defspace_t *work_spaces[qfo_num_spaces] = { + 0, 0, 0, + work_near_data, + work_far_data, + work_entity_data, + 0, + }; + + if (space < 0 || space >= qfo_num_spaces || !work_spaces[space]) + internal_error (0, "bad space for add_data (): %d", space); + defspace_add_data (work_spaces[space], data->d.data, data->data_size); + work->spaces[space].d.data = work_spaces[space]->data; + work->spaces[space].data_size = work_spaces[space]->size; +} + +#define QFOSTR(q,s) ((q)->spaces[qfo_strings_space].d.strings + (s)) +#define WORKSTR(q,s) QFOSTR (work, s) + +static void +update_relocs (qfo_t *qfo) { int i; - - funcgroup_add_funcs (&funcs, qfo->funcs, qfo->num_funcs); - for (i = func_base; i < funcs.num_funcs; i++) { - qfo_func_t *func = funcs.funcs + i; -// func->name = strpool_addstr (strings, qfo->strings + func->name); -// func->file = strpool_addstr (strings, qfo->strings + func->file); - if (func->code) - func->code += code_base; -// if (func->num_local_defs) { -// int def_num = local_defs.num_defs; -// qfo_def_t *d; -// defgroup_add_defs (&local_defs, qfo->defs + func->local_defs, -// func->num_local_defs); -// func->local_defs = def_num; -// for (d = local_defs.defs + def_num; def_num < local_defs.num_defs; -// d++, def_num++) -// fixup_def (qfo, d, def_num); -// } - if (func->line_info) - func->line_info += line_base; - func->relocs += reloc_base; - } -} - -static void -add_lines (qfo_t *qfo) -{ - int i; - - if (lines.num_lines + qfo->num_lines > lines.max_lines) { - lines.max_lines = RUP (lines.num_lines + qfo->num_lines, 16384); - lines.lines = realloc (lines.lines, - lines.max_lines * sizeof (pr_lineno_t)); - } - lines.num_lines += qfo->num_lines; - memcpy (lines.lines + line_base, qfo->lines, - qfo->num_lines * sizeof (pr_lineno_t)); - for (i = line_base; i < lines.num_lines; i++) { - pr_lineno_t *line = lines.lines + i; - if (line->line) - line->fa.addr += code_base; - else - line->fa.func += func_base; - } -} - -static void -fixup_relocs (void) -{ - defref_t *_d; qfo_reloc_t *reloc; - qfo_def_t *def, *field_def; -// qfo_func_t *func; + + for (reloc = qfo->relocs, i = 0; i < qfo->num_relocs; i++, reloc++) { + if (!reloc->space) { + // code space is implied + reloc->offset += work->spaces[qfo_code_space].data_size; + } else if (reloc->space < 0 || reloc->space >= qfo->num_spaces) { + //FIXME proper diagnostic + fprintf (stderr, "bad reloc space: %d", reloc->space); + reloc->type = rel_none; + } else if (reloc->space < qfo_num_spaces) { + reloc->offset += work->spaces[reloc->space].data_size; + } else { + reloc->space += work->num_spaces; + } + reloc->def += work->num_defs; + } +} + +static void +update_defs (qfo_t *qfo) +{ + int space; int i; - - for (i = 0; i < final_relocs.num_relocs; i++) { - reloc = final_relocs.relocs + i; - def = 0; - switch ((reloc_type)reloc->type) { - case rel_none: - break; - - case rel_op_a_def: - case rel_op_b_def: - case rel_op_c_def: - case rel_def_def: - case rel_def_field: - case rel_op_a_def_ofs: - case rel_op_b_def_ofs: - case rel_op_c_def_ofs: - case rel_def_def_ofs: - case rel_def_field_ofs: - def = defs.defs + reloc->def; - if (def->flags & (QFOD_EXTERNAL | QFOD_LOCAL | QFOD_ABSOLUTE)) - continue; - break; - - case rel_def_op: - case rel_op_a_op: - case rel_op_b_op: - case rel_op_c_op: - case rel_def_func: - case rel_def_string: - break; - } - switch ((reloc_type)reloc->type) { - case rel_none: - break; - case rel_op_a_def: - code->code[reloc->offset].a = def->offset; - break; - case rel_op_b_def: - code->code[reloc->offset].b = def->offset; - break; - case rel_op_c_def: - code->code[reloc->offset].c = def->offset; - break; - case rel_op_a_op: - case rel_op_b_op: - case rel_op_c_op: - case rel_op_a_def_ofs: - case rel_op_b_def_ofs: - case rel_op_c_def_ofs: - case rel_def_def_ofs: - case rel_def_field_ofs: - break; - case rel_def_op: - DATA (reloc->offset)->integer_var = reloc->def; - break; - case rel_def_def: - DATA (reloc->offset)->integer_var = def->offset; - break; - case rel_def_func: - DATA (reloc->offset)->func_var = reloc->def + 1; - break; - case rel_def_string: - break; - case rel_def_field: - _d = Hash_Find (field_defs, STRING (def->name)); - if (_d) { // null if not initialized - field_def = deref_def (_d, &fields); - DATA (reloc->offset)->integer_var = field_def->offset; - } - break; - } - } - for (i = 0; i < defs.num_defs; i++) { - def = defs.defs + i; -// if (def->basic_type == ev_func -// && (def->flags & QFOD_INITIALIZED) -// && !(def->flags & (QFOD_LOCAL | QFOD_EXTERNAL | QFOD_ABSOLUTE))) { -// pr_type_t *var = DATA (def->offset); -// if (var->func_var) { -// func = funcs.funcs + var->func_var - 1; -// func->def = i; -// } -// } - } -} - -static void -move_def (hashtab_t *deftab, qfo_def_t *d) -{ - defref_t *_d; qfo_def_t *def; - int def_num = defs.num_defs; - pr_int_t j; - defgroup_add_defs (&defs, d, 1); - def = defs.defs + def_num; - def->relocs = final_relocs.num_relocs; - relocgroup_add_relocs (&final_relocs, relocs.relocs + d->relocs, - d->num_relocs); - for (j = 0; j < d->num_relocs; j++) { - relocs.relocs[d->relocs + j].type = rel_none; - final_relocs.relocs[def->relocs + j].def = def_num; - } -// if ((d->flags & QFOD_CONSTANT) && d->basic_type == ev_func) { -// qfo_func_t *func; -// pr_type_t *var = DATA (d->offset); - -// if (var->func_var) { -// func = funcs.funcs + var->func_var - 1; -// func->def = def_num; -// } -// } - if (deftab) { - while ((_d = Hash_Del (deftab, STRING (def->name)))) { - int def_relocs; - d = deref_def (_d, &global_defs); - relocgroup_add_relocs (&final_relocs, relocs.relocs + d->relocs, - d->num_relocs); - def_relocs = def->relocs + def->num_relocs; - def->num_relocs += d->num_relocs; - for (j = 0; j < d->num_relocs; j++) { - relocs.relocs[d->relocs + j].type = rel_none; - final_relocs.relocs[def_relocs + j].def = def_num; - } - memset (d, 0, sizeof (*d)); + for (space = 0; space < qfo->num_spaces; space++) { + if (space == qfo_type_space) + continue; // complicated. handle separately + for (def = qfo->spaces[space].defs, i = 0; + i < qfo->spaces[space].num_defs; i++, def++) { + //XXX type handled later + def->name = add_string (QFOSTR (qfo, def->name)); + if (space < qfo_num_spaces) + def->offset += work->spaces[space].data_size; + def->relocs += work->num_relocs; + def->file = add_string (QFOSTR (qfo, def->file)); } } } static void -merge_defgroups (void) +update_funcs (qfo_t *qfo) { - int local_base, i; - pr_int_t j; - qfo_def_t *def; - defref_t *d; + int i; qfo_func_t *func; - static qfo_def_t null_def; - for (i = 0; i < global_defs.num_defs; i++) { - const char *name; - def = global_defs.defs + i; - if (memcmp (def, &null_def, sizeof (*def)) == 0) - continue; - name = STRING (def->name); - if ((d = Hash_Del (defined_defs, name))) - move_def (defined_defs, deref_def (d, &global_defs)); - else if ((d = Hash_Del (extern_defs, name))) - move_def (extern_defs, deref_def (d, &global_defs)); - else if (!(def->flags & (QFOD_GLOBAL | QFOD_EXTERNAL))) - move_def (0, def); - } - local_base = defs.num_defs; - for (i = 0; i < local_defs.num_defs; i++) { - move_def (0, local_defs.defs + i); - } - for (i = 0; i < funcs.num_funcs; i++) { - int r = final_relocs.num_relocs; - func = funcs.funcs + i; -// func->local_defs += local_base; - relocgroup_add_relocs (&final_relocs, relocs.relocs + func->relocs, - func->num_relocs); - for (j = 0; j < func->num_relocs; j++) - relocs.relocs[func->relocs + j].type = rel_none; - func->relocs = r; - } - for (i = 0; i < relocs.num_relocs; i = j) { - j = i; - while (j < relocs.num_relocs && relocs.relocs[j].type != rel_none) - j++; - relocgroup_add_relocs (&final_relocs, relocs.relocs + i, j - i); - while (j < relocs.num_relocs && relocs.relocs[j].type == rel_none) - j++; + for (func = qfo->funcs, i = 0; i < qfo->num_funcs; i++, func++) { + func->name = add_string (QFOSTR (qfo, func->name)); + //XXX type handled later + func->file = add_string (QFOSTR (qfo, func->file)); + if (func->code > 0) + func->code += work->spaces[qfo_code_space].data_size; + func->def += work->num_defs; + if (!func->locals_space) { + // no locals (builtin function?) + } else if (func->locals_space < qfo_num_spaces) { + //FIXME proper diagnostic + fprintf (stderr, "function with weird locals: setting to none\n"); + func->locals_space = 0; + } else { + func->locals_space += work->num_spaces - qfo_num_spaces; + } + func->line_info += work->num_lines; + func->relocs += work->num_relocs; } } static void +update_lines (qfo_t *qfo) +{ + int i; + pr_lineno_t *lineno; + + for (lineno = qfo->lines, i = 0; i < qfo->num_lines; i++, lineno++) { + if (lineno->line) + lineno->fa.addr += work->spaces[qfo_code_space].data_size; + else + lineno->fa.func += work->num_funcs; + } +} + +static __attribute__ ((used)) void define_def (const char *name, etype_t basic_type, const char *full_type, unsigned flags, int size, int v) { - qfo_def_t d; - pr_type_t *val = calloc (size, sizeof (pr_type_t)); - - val->integer_var = v; - - memset (&d, 0, sizeof (d)); - -// d.basic_type = basic_type; -// d.full_type = strpool_addstr (type_strings, full_type); - d.name = strpool_addstr (strings, name); - d.offset = data->size; - if (basic_type == ev_field) { - d.relocs = relocs.num_relocs; - d.num_relocs = 1; - } - d.flags = QFOD_GLOBAL | flags; - - defspace_add_data (data, val, size); - defgroup_add_defs (&global_defs, &d, 1); - process_def (global_defs.defs + global_defs.num_defs - 1); - - if (basic_type == ev_field) { - int def_num = global_defs.num_defs - 1; - qfo_def_t *def = global_defs.defs + def_num; - qfo_reloc_t rel = {def->offset, rel_def_field, def_num}; - relocgroup_add_relocs (&relocs, &rel, 1); - process_field (def); - } - free (val); } void linker_begin (void) { - size_t i; + work = qfo_new (); + work->spaces = calloc (qfo_num_spaces, sizeof (qfo_mspace_t)); + work->num_spaces = qfo_num_spaces; - extern_defs = Hash_NewTable (16381, defs_get_key, 0, &global_defs); - defined_defs = Hash_NewTable (16381, defs_get_key, 0, &global_defs); - field_defs = Hash_NewTable (16381, defs_get_key, 0, &fields); - code = codespace_new (); - data = new_defspace (); - far_data = new_defspace (); - entity = new_defspace (); - strings = strpool_new (); - type_strings = strpool_new (); - - pr.strings = strings; - if (!options.partial_link) { - dstring_t *encoding = dstring_new (); - - for (i = 0; - i < sizeof (builtin_symbols) / sizeof (builtin_symbols[0]); - i++) { - etype_t basic_type = builtin_symbols[i].type->type; - int size = type_size (builtin_symbols[i].type); - - dstring_clearstr (encoding); - encode_type (encoding, builtin_symbols[i].type); - define_def (builtin_symbols[i].name, basic_type, encoding->str, - builtin_symbols[i].flags, size, 0); - } - } + // adding data will take care of connecting the work qfo spaces with + // the actual space data + work_strings = strpool_new (); + work_code = codespace_new (); + work_near_data = new_defspace(); + work_far_data = new_defspace(); + work_entity_data = new_defspace(); + work_type_data = new_defspace(); } static void linker_add_qfo (qfo_t *qfo) { - code_base = code->size; - data_base = data->size; - far_data_base = far_data->size; - reloc_base = relocs.num_relocs; - func_base = funcs.num_funcs; - line_base = lines.num_lines; - entity_base = entity->size; + update_relocs (qfo); + update_defs (qfo); + update_funcs (qfo); + update_lines (qfo); -// codespace_addcode (code, qfo->code, qfo->code_size); -// defspace_add_data (data, qfo->data, qfo->data_size); -// defspace_add_data (far_data, qfo->far_data, qfo->far_data_size); -// defspace_add_data (entity, 0, qfo->entity_fields); - add_strings (qfo); - add_relocs (qfo); - add_funcs (qfo); - add_defs (qfo); - add_lines (qfo); + add_qfo_strings (&qfo->spaces[qfo_strings_space]); + add_code (&qfo->spaces[qfo_code_space]); + add_data (qfo_near_data_space, &qfo->spaces[qfo_near_data_space]); + add_data (qfo_far_data_space, &qfo->spaces[qfo_far_data_space]); + add_data (qfo_entity_space, &qfo->spaces[qfo_entity_space]); + //FIXME handle type data } int @@ -745,6 +297,18 @@ linker_add_object_file (const char *filename) qfo = qfo_open (filename); if (!qfo) return 1; + if (qfo->num_spaces < qfo_num_spaces + || qfo->spaces[qfo_null_space].type != qfos_null + || qfo->spaces[qfo_strings_space].type != qfos_string + || qfo->spaces[qfo_code_space].type != qfos_code + || qfo->spaces[qfo_near_data_space].type != qfos_data + || qfo->spaces[qfo_far_data_space].type != qfos_data + || qfo->spaces[qfo_entity_space].type != qfos_entity + || qfo->spaces[qfo_type_space].type != qfos_type) { + //FIXME proper diagnostic + fprintf (stderr, "%s: missing or mangled standard spaces", filename); + return 1; + } if (options.verbosity >= 2) puts (filename); @@ -755,6 +319,14 @@ linker_add_object_file (const char *filename) return 0; } +typedef struct path_s { + struct path_s *next; + const char *path; +} path_t; + +static path_t *path_head; +static path_t **path_tail = &path_head; + int linker_add_lib (const char *libname) { @@ -827,9 +399,10 @@ linker_add_lib (const char *libname) return 0; } -static void +static __attribute__ ((used)) void undefined_def (qfo_def_t *def) { +#if 0 qfo_def_t line_def; pr_int_t i; qfo_reloc_t *reloc = relocs.relocs + def->relocs; @@ -871,11 +444,13 @@ undefined_def (qfo_def_t *def) def_error (def, "undefined symbol %s", STRING (def->name)); } } +#endif } qfo_t * linker_finish (void) { +#if 0 defref_t **undef_defs, **defref; qfo_t *qfo; @@ -931,6 +506,8 @@ linker_finish (void) qfo_add_types (qfo, type_strings->strings, type_strings->size); // qfo->entity_fields = entity->size; return qfo; +#endif + return work; } void @@ -958,25 +535,25 @@ def_error (qfo_def_t *def, const char *fmt, ...) pr.source_file = def->file; pr.source_line = def->line; - pr.strings = strings; +// pr.strings = strings; error (0, "%s", string->str); } -//static void -//def_warning (qfo_def_t *def, const char *fmt, ...) -//{ -// va_list args; -// static dstring_t *string; -// -// if (!string) -// string = dstring_new (); -// -// va_start (args, fmt); -// dvsprintf (string, fmt, args); -// va_end (args); -// -// pr.source_file = def->file; -// pr.source_line = def->line; +static void +def_warning (qfo_def_t *def, const char *fmt, ...) +{ + va_list args; + static dstring_t *string; + + if (!string) + string = dstring_new (); + + va_start (args, fmt); + dvsprintf (string, fmt, args); + va_end (args); + + pr.source_file = def->file; + pr.source_line = def->line; // pr.strings = strings; -// warning (0, "%s", string->str); -//} + warning (0, "%s", string->str); +} diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 0f898e77e..08a1bb916 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -556,7 +556,7 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr) qfo_t * qfo_new (void) { - return 0; + return calloc (1, sizeof (qfo_t)); } void