[qfcc] Support generating a C array of the output

I'd far rather use #embed, but gotta wait for gcc-15.
This commit is contained in:
Bill Currie 2025-01-24 18:53:40 +09:00
parent a3a4ca90b5
commit 0071c138bd
6 changed files with 71 additions and 12 deletions

View file

@ -239,6 +239,12 @@ command line.
Unsupported options are ignored. Unsupported options are ignored.
The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument: The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument:
.TP
.B c-array[=name]
Generate a C source file with an array instead of the default binary format
for the target. Optionally, the default name (generated from the source file
name) can be overriden.
.TP .TP
.B const-initializers .B const-initializers
Treat initialized globals as constants. Treat initialized globals as constants.

View file

@ -60,6 +60,9 @@ typedef struct {
bool no_int; // int type is not supported bool no_int; // int type is not supported
bool no_vararg; // variadic functions (...) not supported bool no_vararg; // variadic functions (...) not supported
bool c_array; // produce a C array for output
const char *c_array_name; // override for array name
bool help; bool help;
} code_options_t; } code_options_t;

View file

@ -108,6 +108,7 @@ extern pr_info_t pr;
#define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data) #define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data)
bool write_output (const char *filename, void *data, size_t bytes);
const char *file_basename (const char *filename, int keepdot) __attribute__((pure)); const char *file_basename (const char *filename, int keepdot) __attribute__((pure));
extern int pre_yydebug; extern int pre_yydebug;

View file

@ -228,6 +228,9 @@ code_usage (void)
printf ("%s - QuakeForge Code Compiler\n", this_program); printf ("%s - QuakeForge Code Compiler\n", this_program);
printf ("Code generation options\n"); printf ("Code generation options\n");
printf ( printf (
" c-array[=name] Generate a C file with an array instead of the\n"
" default output for the target, with optional\n"
" override for the array name\n"
" [no-]const-initializers Treat initialized globals as constants.\n" " [no-]const-initializers Treat initialized globals as constants.\n"
" [no-]cow Allow assignment to initialized globals.\n" " [no-]cow Allow assignment to initialized globals.\n"
" [no-]cpp Preprocess all input files with cpp.\n" " [no-]cpp Preprocess all input files with cpp.\n"
@ -574,6 +577,14 @@ parse_code_option (const char *opt)
if (OPTION(code, opt, "const-initializers", const_initializers, flag)) { if (OPTION(code, opt, "const-initializers", const_initializers, flag)) {
return true; return true;
} }
if (OPTION(code, opt, "c-array", c_array, flag)) {
return true;
}
if (!strncasecmp (opt, "c-array=", 8)) {
options.code.c_array = true;
options.code.c_array_name = save_string (opt + 8);
return true;
}
return false; return false;
} }

View file

@ -54,6 +54,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <ctype.h>
#include <QF/cbuf.h> #include <QF/cbuf.h>
#include <QF/crc.h> #include <QF/crc.h>
@ -205,7 +206,6 @@ static int
WriteProgs (dprograms_t *progs, int size) WriteProgs (dprograms_t *progs, int size)
{ {
//pr_debug_header_t debug; //pr_debug_header_t debug;
QFile *h;
unsigned i; unsigned i;
dstatement_t *statements; dstatement_t *statements;
@ -251,13 +251,7 @@ WriteProgs (dprograms_t *progs, int size)
for (i = 0; i < progs->globals.count; i++) for (i = 0; i < progs->globals.count; i++)
globals[i].value = LittleLong (globals[i].value); globals[i].value = LittleLong (globals[i].value);
if (!(h = Qopen (options.output_file, "wb"))) return write_output (options.output_file, progs, size);
Sys_Error ("%s: %s\n", options.output_file, strerror(errno));
Qwrite (h, progs, size);
Qclose (h);
return 0;
} }
static int static int
@ -330,6 +324,52 @@ begin_compilation (void)
pr.error_count = 0; pr.error_count = 0;
} }
bool
write_output (const char *filename, void *data, size_t bytes)
{
QFile *file = Qopen (filename, "wb");
if (!file) {
Sys_Error ("%s: %s\n", filename, strerror(errno));
return true;
}
if (options.code.c_array) {
const char *name = options.code.c_array_name;
uint32_t *words = data;
size_t count = bytes / 4;//FIXME asumes bytes is multiple of 4
const char *src = GETSTR (pr.loc.file);
char buf[strlen (src) + 1];
if (!name) {
for (char *d = buf; (*d = *src); d++, src++) {
if (!isalnum ((unsigned char) *d)) {
*d = '_';
}
}
name = buf;
}
Qprintf (file, "uint32_t %s[] = {\n", name);
if (count) {
Qprintf (file, "\t");
}
for (size_t i = 0; i < count; i++) {
Qprintf (file, "0x%08x,", words[i]);
if (i + 1 < count) {
if ((i + 1) % 4) {
Qprintf (file, " ");
} else {
Qprintf (file, "\n\t");
}
} else {
Qprintf (file, "\n");
}
}
Qprintf (file, "};");
} else {
Qwrite (file, data, bytes);
}
Qclose (file);
return false;
}
const char * const char *
file_basename (const char *filename, int keepdot) file_basename (const char *filename, int keepdot)
{ {

View file

@ -2113,10 +2113,8 @@ spirv_write (struct pr_info_s *pr, const char *filename)
ADD_DATA (space, mod->func_declarations); ADD_DATA (space, mod->func_declarations);
ADD_DATA (space, mod->func_definitions); ADD_DATA (space, mod->func_definitions);
QFile *file = Qopen (filename, "wb"); return write_output (filename, space->data,
Qwrite (file, space->data, space->size * sizeof (pr_type_t)); space->size * sizeof (pr_type_t));
Qclose (file);
return false;
} }
void void