mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
[qfcc] create a compilation unit for debug data
The compilation unit stores the directory from which qfcc was run and any source files mentioned. This is similar to dwarf's compilation unit. Right now, this is the only data in the new debug space, but more might come in the future so it seems best to treat the debug space separately in the object files.
This commit is contained in:
parent
65e7df44d3
commit
049b8f392c
8 changed files with 161 additions and 4 deletions
|
@ -34,6 +34,13 @@
|
||||||
#ifndef __QFCC__
|
#ifndef __QFCC__
|
||||||
#include "QF/pr_comp.h"
|
#include "QF/pr_comp.h"
|
||||||
|
|
||||||
|
typedef struct pr_compunit_s {
|
||||||
|
pr_uint_t unit_name;
|
||||||
|
pr_uint_t basedir;
|
||||||
|
pr_uint_t num_files;
|
||||||
|
pr_uint_t files[1];
|
||||||
|
} pr_compunit_t;
|
||||||
|
|
||||||
typedef struct pr_auxfunction_s {
|
typedef struct pr_auxfunction_s {
|
||||||
pr_uint_t function; // function def this aux info is for
|
pr_uint_t function; // function def this aux info is for
|
||||||
pr_uint_t source_line; // first source line for this function
|
pr_uint_t source_line; // first source line for this function
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
void line_info (char *text);
|
void line_info (char *text);
|
||||||
pr_lineno_t *new_lineno (void);
|
pr_lineno_t *new_lineno (void);
|
||||||
|
void add_source_file (const char *file);
|
||||||
|
void debug_finish_module (const char *modname);
|
||||||
|
|
||||||
extern int lineno_base;
|
extern int lineno_base;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ typedef enum qfos_type_e {
|
||||||
qfos_string, ///< strings. char data
|
qfos_string, ///< strings. char data
|
||||||
qfos_entity, ///< entity field defs. no data
|
qfos_entity, ///< entity field defs. no data
|
||||||
qfos_type, ///< type encodings
|
qfos_type, ///< type encodings
|
||||||
|
qfos_debug, ///< debug data
|
||||||
} qfos_type_t;
|
} qfos_type_t;
|
||||||
|
|
||||||
/** Representation of a space in the object file.
|
/** Representation of a space in the object file.
|
||||||
|
@ -283,6 +284,7 @@ enum {
|
||||||
qfo_far_data_space,
|
qfo_far_data_space,
|
||||||
qfo_entity_space,
|
qfo_entity_space,
|
||||||
qfo_type_space,
|
qfo_type_space,
|
||||||
|
qfo_debug_space,
|
||||||
|
|
||||||
qfo_num_spaces
|
qfo_num_spaces
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "QF/darray.h"
|
||||||
#include "QF/pr_comp.h"
|
#include "QF/pr_comp.h"
|
||||||
|
|
||||||
/** \defgroup qfcc_general General functions
|
/** \defgroup qfcc_general General functions
|
||||||
|
@ -68,6 +69,11 @@ typedef struct pr_info_s {
|
||||||
struct defspace_s *entity_data; ///< entity field address space. no
|
struct defspace_s *entity_data; ///< entity field address space. no
|
||||||
///< data is stored in the progs file
|
///< data is stored in the progs file
|
||||||
struct defspace_s *type_data; ///< encoded type information.
|
struct defspace_s *type_data; ///< encoded type information.
|
||||||
|
struct defspace_s *debug_data; ///< additional debug data.
|
||||||
|
struct strpool_s *comp_file_set;
|
||||||
|
struct DARRAY_TYPE (const char *) comp_files;
|
||||||
|
const char *comp_dir;
|
||||||
|
const char *unit_name;
|
||||||
|
|
||||||
struct symtab_s *symtab;
|
struct symtab_s *symtab;
|
||||||
struct symtab_s *entity_fields;
|
struct symtab_s *entity_fields;
|
||||||
|
|
|
@ -44,10 +44,16 @@
|
||||||
#include "QF/pr_comp.h"
|
#include "QF/pr_comp.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "def.h"
|
||||||
|
#include "defspace.h"
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
|
#include "emit.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
|
#include "reloc.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
|
#include "struct.h"
|
||||||
|
#include "type.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
int lineno_base;
|
int lineno_base;
|
||||||
|
@ -79,6 +85,17 @@ pop_source_file (void)
|
||||||
FREE (srclines, tmp);
|
FREE (srclines, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define Sys_Error(fmt...) internal_error(0, fmt)
|
||||||
|
void
|
||||||
|
add_source_file (const char *file)
|
||||||
|
{
|
||||||
|
pr.source_file = ReuseString (file);
|
||||||
|
if (!strpool_findstr (pr.comp_file_set, file)) {
|
||||||
|
strpool_addstr (pr.comp_file_set, file);
|
||||||
|
DARRAY_APPEND (&pr.comp_files, save_string (file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
line_info (char *text)
|
line_info (char *text)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +128,7 @@ line_info (char *text)
|
||||||
while (*p && *p != '\n') // ignore rest
|
while (*p && *p != '\n') // ignore rest
|
||||||
p++;
|
p++;
|
||||||
pr.source_line = line - 1;
|
pr.source_line = line - 1;
|
||||||
pr.source_file = ReuseString (str);
|
add_source_file (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_lineno_t *
|
pr_lineno_t *
|
||||||
|
@ -125,3 +142,67 @@ new_lineno (void)
|
||||||
memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t));
|
memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t));
|
||||||
return &pr.linenos[pr.num_linenos++];
|
return &pr.linenos[pr.num_linenos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_unit_name (def_t *def, void *data, int index)
|
||||||
|
{
|
||||||
|
if (!is_string (def->type)) {
|
||||||
|
internal_error (0, "%s: expected string def", __FUNCTION__);
|
||||||
|
}
|
||||||
|
EMIT_STRING (def->space, D_STRING (def), pr.unit_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_basedir (def_t *def, void *data, int index)
|
||||||
|
{
|
||||||
|
if (!is_string (def->type)) {
|
||||||
|
internal_error (0, "%s: expected string def", __FUNCTION__);
|
||||||
|
}
|
||||||
|
EMIT_STRING (def->space, D_STRING (def), pr.comp_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_num_files (def_t *def, void *data, int index)
|
||||||
|
{
|
||||||
|
if (!is_integer (def->type)) {
|
||||||
|
internal_error (0, "%s: expected int def", __FUNCTION__);
|
||||||
|
}
|
||||||
|
D_INT (def) = pr.comp_files.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_files_item (def_t *def, void *data, int index)
|
||||||
|
{
|
||||||
|
if (!is_array (def->type) || !is_string (def->type->t.array.type)) {
|
||||||
|
internal_error (0, "%s: expected array of string def", __FUNCTION__);
|
||||||
|
}
|
||||||
|
if ((unsigned) index >= pr.comp_files.size) {
|
||||||
|
internal_error (0, "%s: out of bounds index: %d %zd",
|
||||||
|
__FUNCTION__, index, pr.comp_files.size);
|
||||||
|
}
|
||||||
|
EMIT_STRING (def->space, D_STRING (def), pr.comp_files.a[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static def_t *
|
||||||
|
emit_compunit (const char *modname)
|
||||||
|
{
|
||||||
|
static struct_def_t compunit_struct[] = {
|
||||||
|
{"unit_name", &type_string, emit_unit_name},
|
||||||
|
{"basedir", &type_string, emit_basedir},
|
||||||
|
{"num_files", &type_integer, emit_num_files},
|
||||||
|
{"files", 0, emit_files_item},
|
||||||
|
{0, 0}
|
||||||
|
};
|
||||||
|
int count = pr.comp_files.size;
|
||||||
|
|
||||||
|
pr.unit_name = modname;
|
||||||
|
compunit_struct[3].type = array_type (&type_string, count);
|
||||||
|
return emit_structure ("compile_unit", 's', compunit_struct, 0, &pr,
|
||||||
|
pr.debug_data, sc_static);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_finish_module (const char *modname)
|
||||||
|
{
|
||||||
|
emit_compunit (modname);
|
||||||
|
}
|
||||||
|
|
|
@ -154,6 +154,7 @@ static defspace_t *work_near_data;
|
||||||
static defspace_t *work_far_data;
|
static defspace_t *work_far_data;
|
||||||
static defspace_t *work_entity_data;
|
static defspace_t *work_entity_data;
|
||||||
static defspace_t *work_type_data;
|
static defspace_t *work_type_data;
|
||||||
|
static defspace_t *work_debug_data;
|
||||||
static qfo_reloc_t *work_loose_relocs;
|
static qfo_reloc_t *work_loose_relocs;
|
||||||
static int work_num_loose_relocs;
|
static int work_num_loose_relocs;
|
||||||
|
|
||||||
|
@ -163,6 +164,7 @@ static defspace_t **work_spaces[qfo_num_spaces] = {
|
||||||
&work_far_data,
|
&work_far_data,
|
||||||
&work_entity_data,
|
&work_entity_data,
|
||||||
&work_type_data,
|
&work_type_data,
|
||||||
|
&work_debug_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
static dstring_t *linker_current_file;
|
static dstring_t *linker_current_file;
|
||||||
|
@ -684,6 +686,7 @@ linker_begin (void)
|
||||||
work_far_data = defspace_new (ds_backed);
|
work_far_data = defspace_new (ds_backed);
|
||||||
work_entity_data = defspace_new (ds_virtual);
|
work_entity_data = defspace_new (ds_virtual);
|
||||||
work_type_data = defspace_new (ds_backed);
|
work_type_data = defspace_new (ds_backed);
|
||||||
|
work_debug_data = defspace_new (ds_backed);
|
||||||
|
|
||||||
pr.strings = work_strings;
|
pr.strings = work_strings;
|
||||||
|
|
||||||
|
@ -709,6 +712,9 @@ linker_begin (void)
|
||||||
work->spaces[qfo_type_space].type = qfos_type;
|
work->spaces[qfo_type_space].type = qfos_type;
|
||||||
work->spaces[qfo_type_space].d.data = work_type_data->data;
|
work->spaces[qfo_type_space].d.data = work_type_data->data;
|
||||||
work->spaces[qfo_type_space].data_size = work_type_data->size;
|
work->spaces[qfo_type_space].data_size = work_type_data->size;
|
||||||
|
work->spaces[qfo_debug_space].type = qfos_debug;
|
||||||
|
work->spaces[qfo_debug_space].d.data = work_type_data->data;
|
||||||
|
work->spaces[qfo_debug_space].data_size = work_type_data->size;
|
||||||
for (i = 0; i < qfo_num_spaces; i++)
|
for (i = 0; i < qfo_num_spaces; i++)
|
||||||
work->spaces[i].id = i;
|
work->spaces[i].id = i;
|
||||||
|
|
||||||
|
@ -906,6 +912,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_debug_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||||
|
{
|
||||||
|
if (pass != 1)
|
||||||
|
return 0;
|
||||||
|
if (space->type != qfos_debug) {
|
||||||
|
linker_internal_error ("bad space type for add_data_space (): %d",
|
||||||
|
space->type);
|
||||||
|
}
|
||||||
|
add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def);
|
||||||
|
add_data (qfo_debug_space, space);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_funcs (qfo_t *qfo)
|
process_funcs (qfo_t *qfo)
|
||||||
{
|
{
|
||||||
|
@ -1002,6 +1022,7 @@ linker_add_qfo (qfo_t *qfo)
|
||||||
process_strings_space,
|
process_strings_space,
|
||||||
process_entity_space,
|
process_entity_space,
|
||||||
process_type_space,
|
process_type_space,
|
||||||
|
process_debug_space,
|
||||||
};
|
};
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int pass;
|
int pass;
|
||||||
|
@ -1014,7 +1035,7 @@ linker_add_qfo (qfo_t *qfo)
|
||||||
work_func_base = work->num_funcs;
|
work_func_base = work->num_funcs;
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (pass = 0; pass < 2; pass++) {
|
||||||
for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) {
|
for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) {
|
||||||
if ((int) space->type < 0 || space->type > qfos_type) {
|
if ((int) space->type < 0 || space->type > qfos_debug) {
|
||||||
linker_error ("bad space type");
|
linker_error ("bad space type");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,7 @@ qfo_count_stuff (qfo_t *qfo, pr_info_t *pr)
|
||||||
qfo_count_space_stuff (qfo, pr->far_data);
|
qfo_count_space_stuff (qfo, pr->far_data);
|
||||||
qfo_count_space_stuff (qfo, pr->entity_data);
|
qfo_count_space_stuff (qfo, pr->entity_data);
|
||||||
qfo_count_space_stuff (qfo, pr->type_data);
|
qfo_count_space_stuff (qfo, pr->type_data);
|
||||||
|
qfo_count_space_stuff (qfo, pr->debug_data);
|
||||||
qfo_count_function_stuff (qfo, pr->func_head);
|
qfo_count_function_stuff (qfo, pr->func_head);
|
||||||
qfo->num_relocs += count_relocs (pr->relocs);
|
qfo->num_relocs += count_relocs (pr->relocs);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +270,24 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
||||||
space->id = qfo_type_space;
|
space->id = qfo_type_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
qfo_init_debug_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
||||||
|
qfo_mspace_t *space, defspace_t *data)
|
||||||
|
{
|
||||||
|
size_t size = data->size * sizeof (*data->data);
|
||||||
|
data->qfo_space = space - qfo->spaces;
|
||||||
|
space->type = qfos_debug;
|
||||||
|
space->defs = *defs;
|
||||||
|
space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs);
|
||||||
|
space->d.data = 0;
|
||||||
|
if (data->data) {
|
||||||
|
space->d.data = malloc (size);
|
||||||
|
memcpy (space->d.data, data->data, size);
|
||||||
|
}
|
||||||
|
space->data_size = data->size;
|
||||||
|
space->id = qfo_debug_space;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
||||||
qfo_mspace_t *space, function_t *functions)
|
qfo_mspace_t *space, function_t *functions)
|
||||||
|
@ -333,6 +352,8 @@ qfo_from_progs (pr_info_t *pr)
|
||||||
pr->entity_data);
|
pr->entity_data);
|
||||||
qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space],
|
qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space],
|
||||||
pr->type_data);
|
pr->type_data);
|
||||||
|
qfo_init_debug_space (qfo, &def, &reloc, &qfo->spaces[qfo_debug_space],
|
||||||
|
pr->debug_data);
|
||||||
|
|
||||||
qfo_encode_functions (qfo, &def, &reloc, qfo->spaces + qfo_num_spaces,
|
qfo_encode_functions (qfo, &def, &reloc, qfo->spaces + qfo_num_spaces,
|
||||||
pr->func_head);
|
pr->func_head);
|
||||||
|
@ -382,6 +403,8 @@ qfo_space_size (qfo_mspace_t *space)
|
||||||
return 0;
|
return 0;
|
||||||
case qfos_type:
|
case qfos_type:
|
||||||
return space->data_size * sizeof (*space->d.data);
|
return space->data_size * sizeof (*space->d.data);
|
||||||
|
case qfos_debug:
|
||||||
|
return space->data_size * sizeof (*space->d.data);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +430,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type)
|
||||||
case qfos_data:
|
case qfos_data:
|
||||||
case qfos_entity:
|
case qfos_entity:
|
||||||
case qfos_type:
|
case qfos_type:
|
||||||
|
case qfos_debug:
|
||||||
for (val = (pr_type_t *) space, c = 0; c < size; c++, val++)
|
for (val = (pr_type_t *) space, c = 0; c < size; c++, val++)
|
||||||
val->integer_var = LittleLong (val->integer_var);
|
val->integer_var = LittleLong (val->integer_var);
|
||||||
break;
|
break;
|
||||||
|
@ -949,6 +973,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
||||||
progs->numglobals += progs->numglobaldefs * type_size (&type_xdef);
|
progs->numglobals += progs->numglobaldefs * type_size (&type_xdef);
|
||||||
progs->numglobals += progs->numfielddefs * type_size (&type_xdef);
|
progs->numglobals += progs->numfielddefs * type_size (&type_xdef);
|
||||||
progs->entityfields = qfo->spaces[qfo_entity_space].data_size;
|
progs->entityfields = qfo->spaces[qfo_entity_space].data_size;
|
||||||
|
// qfo_debug_space does not go in the progs file
|
||||||
*size += progs->numstatements * sizeof (dstatement_t);
|
*size += progs->numstatements * sizeof (dstatement_t);
|
||||||
*size += progs->numglobaldefs * sizeof (ddef_t);
|
*size += progs->numglobaldefs * sizeof (ddef_t);
|
||||||
*size += progs->numfielddefs * sizeof (ddef_t);
|
*size += progs->numfielddefs * sizeof (ddef_t);
|
||||||
|
|
|
@ -141,6 +141,12 @@ InitData (void)
|
||||||
defspace_delete (pr.far_data);
|
defspace_delete (pr.far_data);
|
||||||
defspace_delete (pr.entity_data);
|
defspace_delete (pr.entity_data);
|
||||||
defspace_delete (pr.type_data);
|
defspace_delete (pr.type_data);
|
||||||
|
defspace_delete (pr.debug_data);
|
||||||
|
strpool_delete (pr.comp_file_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pr.comp_files.a) {
|
||||||
|
DARRAY_CLEAR (&pr.comp_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pr.linenos) {
|
if (pr.linenos) {
|
||||||
|
@ -173,6 +179,10 @@ InitData (void)
|
||||||
pr.type_data = defspace_new (ds_backed);
|
pr.type_data = defspace_new (ds_backed);
|
||||||
defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor
|
defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor
|
||||||
|
|
||||||
|
pr.debug_data = defspace_new (ds_backed);
|
||||||
|
pr.comp_file_set = strpool_new ();
|
||||||
|
DARRAY_INIT (&pr.comp_files, 16);
|
||||||
|
|
||||||
pr.symtab = new_symtab (0, stab_global);
|
pr.symtab = new_symtab (0, stab_global);
|
||||||
pr.symtab->space = pr.near_data;
|
pr.symtab->space = pr.near_data;
|
||||||
current_symtab = pr.symtab;
|
current_symtab = pr.symtab;
|
||||||
|
@ -374,7 +384,8 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
|
||||||
InitData ();
|
InitData ();
|
||||||
chain_initial_types ();
|
chain_initial_types ();
|
||||||
begin_compilation ();
|
begin_compilation ();
|
||||||
pr.source_file = ReuseString (file);
|
pr.comp_dir = save_cwd ();
|
||||||
|
add_source_file (file);
|
||||||
err = yyparse () || pr.error_count;
|
err = yyparse () || pr.error_count;
|
||||||
fclose (*yyin);
|
fclose (*yyin);
|
||||||
if (cpp_name && !options.save_temps) {
|
if (cpp_name && !options.save_temps) {
|
||||||
|
@ -392,6 +403,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
|
||||||
class_finish_module ();
|
class_finish_module ();
|
||||||
err = pr.error_count;
|
err = pr.error_count;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
debug_finish_module (obj);
|
||||||
qfo = qfo_from_progs (&pr);
|
qfo = qfo_from_progs (&pr);
|
||||||
err = qfo_write (qfo, obj);
|
err = qfo_write (qfo, obj);
|
||||||
qfo_delete (qfo);
|
qfo_delete (qfo);
|
||||||
|
@ -630,7 +642,7 @@ compile_file (const char *filename)
|
||||||
if (!*yyin)
|
if (!*yyin)
|
||||||
return !options.preprocess_only;
|
return !options.preprocess_only;
|
||||||
|
|
||||||
pr.source_file = ReuseString (filename);
|
add_source_file (filename);
|
||||||
pr.source_line = 1;
|
pr.source_line = 1;
|
||||||
clear_frame_macros ();
|
clear_frame_macros ();
|
||||||
err = yyparse () || pr.error_count;
|
err = yyparse () || pr.error_count;
|
||||||
|
@ -774,6 +786,7 @@ progs_src_compile (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
class_finish_module ();
|
class_finish_module ();
|
||||||
|
debug_finish_module (options.output_file);
|
||||||
qfo = qfo_from_progs (&pr);
|
qfo = qfo_from_progs (&pr);
|
||||||
if (options.compile) {
|
if (options.compile) {
|
||||||
qfo_write (qfo, options.output_file);
|
qfo_write (qfo, options.output_file);
|
||||||
|
|
Loading…
Reference in a new issue