Add an option to dump frame files.

After running across a question about lists of animation frames and states,
I decided giving qfcc the ability to generate such lists might be a nice
distraction from the optimizer :) Works for both progs.src and separate
compilation. No frame file is generated if no macros have been created.
This commit is contained in:
Bill Currie 2012-11-21 20:50:45 +09:00
parent d0c37bbc51
commit 1d34da26f7
7 changed files with 79 additions and 5 deletions

View file

@ -75,6 +75,16 @@ Allow extended keywords in traditional mode.
Generate \fIfiles.dat\fP.
This list is created by checking the parameters to the precache_* functions.
.TP
.B \-\-frames
Generate \fI<source>.frame\fP files.
For each source file (listed either on the command line, or in
\fBprogs.src\fP, write a file whose name is the base name of the source
file with an extension of \fB.frame\fP, and contains a list of frame macro
names with their associated frame numbers. Eg, \fBplayer.qc\fP will produce
\fBplayer.frame\fPa. Note that files that do not create frame macros will
not generate a frame file. At this time, the file is always written to the
current directory.
.TP
.B \-g
Generate debugging info.
Synonym for \fB\-\-code debug\fP.

View file

@ -33,8 +33,10 @@
extern int grab_frame;
extern int grab_other;
extern int grab_write;
int do_grab (char *token);
void add_frame_macro (char *token);
int do_grab (const char *token);
void add_frame_macro (const char *token);
void write_frame_macros (const char *filename);
#endif//__grab_h

View file

@ -87,6 +87,7 @@ typedef struct {
qboolean no_default_paths; // no default -I or -L
qboolean save_temps; // save temporary files
qboolean files_dat; // generate files.dat
qboolean frames_files; // generate <basename>.frame files
qboolean progdefs_h; // generate progdefs.h
qboolean qccx_escapes; // use qccx escapes instead of standard C
int traditional; // behave more like qcc

View file

@ -41,6 +41,7 @@
#include <ctype.h>
#include "QF/hash.h"
#include "QF/quakeio.h"
#include "diagnostic.h"
#include "expr.h"
@ -51,6 +52,7 @@
int grab_frame;
int grab_other;
int grab_write;
static hashtab_t *frame_tab;
static hashtab_t *grab_tab;
@ -62,6 +64,8 @@ typedef struct frame_s {
} frame_t;
static frame_t *free_frames;
static frame_t *frame_list;
static frame_t **frame_tail = &frame_list;
static frame_t grab_list[] = {
{0, "cd", 0},
@ -87,7 +91,7 @@ frame_free (void *_f, void *unused)
}
int
do_grab (char *token)
do_grab (const char *token)
{
static int initialized;
frame_t *frame;
@ -110,6 +114,8 @@ do_grab (char *token)
clear_frame_macros ();
return -grab_other;
}
if (!strcmp (token, "frame_write"))
return -grab_write;
if (Hash_Find (grab_tab, token))
return -grab_other;
frame = Hash_Find (frame_tab, token);
@ -121,7 +127,7 @@ do_grab (char *token)
static int frame_number;
void
add_frame_macro (char *token)
add_frame_macro (const char *token)
{
frame_t *frame;
@ -133,6 +139,8 @@ add_frame_macro (char *token)
}
ALLOC (1024, frame_t, frames, frame);
*frame_tail = frame;
frame_tail = &frame->next;
frame->name = save_string (token);
frame->num = frame_number++;
Hash_Add (frame_tab, frame);
@ -142,7 +150,22 @@ void
clear_frame_macros (void)
{
frame_number = 0;
frame_tail = &frame_list;
frame_list = 0;
if (frame_tab)
Hash_FlushTable (frame_tab);
}
void
write_frame_macros (const char *filename)
{
frame_t *frame;
QFile *file;
if (!frame_list)
return;
file = Qopen (filename, "wt");
for (frame = frame_list; frame; frame = frame->next)
Qprintf (file, "%s %d\n", frame->name, frame->num);
Qclose (file);
}

View file

@ -63,6 +63,7 @@ enum {
OPT_BLOCK_DOT,
OPT_CPP,
OPT_EXTENDED,
OPT_FRAMES,
OPT_INCLUDE,
OPT_NO_DEFAULT_PATHS,
OPT_PROGDEFS,
@ -78,6 +79,7 @@ static struct option const long_options[] = {
{"define", required_argument, 0, 'D'},
{"extended", no_argument, 0, OPT_EXTENDED},
{"files", no_argument, 0, 'F'},
{"frames", no_argument, 0, OPT_FRAMES},
{"help", no_argument, 0, 'h'},
{"include", required_argument, 0, OPT_INCLUDE},
{"no-default-paths", no_argument, 0, OPT_NO_DEFAULT_PATHS},
@ -143,6 +145,7 @@ usage (int status)
" -E Only preprocess\n"
" --extended Allow extended keywords in traditional mode\n"
" -F, --files Generate files.dat\n"
" --frames Generate <source>.frame files\n"
" -g Generate debugging info\n"
" -h, --help Display this help and exit\n"
" -I DIR Set directories for the preprocessor\n"
@ -354,6 +357,9 @@ DecodeArgs (int argc, char **argv)
case 'g': // debug
options.code.debug = true;
break;
case OPT_FRAMES:
options.frames_files = 1;
break;
case OPT_EXTENDED:
options.traditional = 1;
options.advanced = false;

View file

@ -100,11 +100,12 @@ ELLIPSIS \.\.\.
FRAMEID {ID}(\.{ID})*
STRING \"(\\.|[^"\\])*\"
%x GRAB_FRAME GRAB_OTHER COMMENT
%x GRAB_FRAME GRAB_OTHER GRAB_WRITE COMMENT
%%
grab_frame = GRAB_FRAME;
grab_other = GRAB_OTHER;
grab_write = GRAB_WRITE;
"/*" { BEGIN (COMMENT); }
<COMMENT>"/*" { warning (0, "nested /* in comment"); }
@ -234,6 +235,11 @@ STRING \"(\\.|[^"\\])*\"
<GRAB_FRAME>{FRAMEID} add_frame_macro (yytext);
<GRAB_OTHER>[^\r\n]* /* skip */
<GRAB_WRITE>{STRING} {
const char *s = make_string (yytext, 0);
write_frame_macros (s);
BEGIN (GRAB_OTHER); // ignore rest of line
}
<*>\r*\n {
pr.source_line++;

View file

@ -76,6 +76,7 @@
#include "emit.h"
#include "expr.h"
#include "function.h"
#include "grab.h"
#include "idstuff.h"
#include "linker.h"
#include "method.h"
@ -306,6 +307,25 @@ strip_path (const char *filename)
return filename;
}
static const char *
basename (const char *filename)
{
const char *p;
const char *dot;
static dstring_t *base;
if (!base)
base = dstring_new ();
for (dot = p = filename + strlen (filename); p > filename; p--) {
if (p[-1] == '/' || p[-1] == '\\')
break;
if (p[0] == '.')
dot = p;
}
dstring_copysubstr (base, p, dot - p);
return base->str;
}
static void
setup_sym_file (const char *output_file)
{
@ -368,6 +388,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
exit (1);
}
}
write_frame_macros (va ("%s.frame", basename (file)));
if (!err) {
qfo_t *qfo;
@ -696,9 +717,14 @@ progs_src_compile (void)
fprintf (single, "#line %d \"%s\"\n", script->line,
script->file);
fprintf (single, "#include \"%s\"\n", qc_filename->str);
if (options.frames_files)
fprintf (single, "$frame_write \"%s.frame\"\n",
basename (qc_filename->str));
} else {
if (compile_file (qc_filename->str))
return 1;
write_frame_macros (va ("%s.frame",
basename (qc_filename->str)));
}
if (!Script_TokenAvailable (script, 0))
break;