qfcc: Preparation for getopt.

This commit is contained in:
Jeff Teunissen 2001-10-26 06:43:56 +00:00
parent 1fab17ab33
commit 581411e9e2
7 changed files with 125 additions and 51 deletions

View file

@ -555,13 +555,24 @@ int CopyString (const char *str);
int ReuseString (const char *str);
typedef struct {
int cow; // copy on write for constants
int version; // maximum progs version to support (eg, 6 for id)
int warn_error; // treat warnings as errors
int quiet; // not so much chatter
int debug; // produce debug info
int undefined_function_warning; // print a warning when a function isn't defined
int warn_uninitialized; // warn for uninitialized vars
qboolean cow; // Turn constants into variables if written to
qboolean debug; // Generate debug info for the engine
int progsversion; // Progs version to generate code for
} code_options_t;
typedef struct {
qboolean promote; // Promote warnings to errors
qboolean cow; // Warn on copy-on-write detection
qboolean undefined_function; // Warn on undefined function use
qboolean uninited_variable; // Warn on use of uninitialized vars
qboolean vararg_integer; // Warn on passing an integer to vararg func
} warn_options_t;
typedef struct {
code_options_t code; // Code generation options
warn_options_t warnings; // Warning options
int verbosity; // 0=silent, goes up to 2 currently
} options_t;
extern options_t options;

View file

@ -54,7 +54,7 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_
error (&e, "ice ice baby\n");
abort ();
}
if (options.debug) {
if (options.code.debug) {
int line = sline - lineno_base;
if (line != linenos[num_linenos - 1].line) {
@ -177,13 +177,15 @@ emit_assign_expr (expr_t *e)
emit_statement (e->line, op, def_b, def_a, 0);
} else {
if (def_a->constant) {
if (options.cow) {
if (options.code.cow) {
int size = type_size [def_a->type->type];
int ofs = PR_NewLocation (def_a->type);
memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size);
def_a->ofs = ofs;
def_a->constant = 0;
//warning (e1, "assignment to constant %s", def_a->name);
if (options.warnings.cow)
warning (e1, "assignment to constant %s (Moooooooo!)", def_a->name);
} else {
error (e1, "assignment to constant %s", def_a->name);
}

View file

@ -123,7 +123,7 @@ get_type (expr_t *e)
case ex_temp:
return e->e.temp.type;
case ex_integer:
if (options.version == PROG_ID_VERSION) {
if (options.code.progsversion == PROG_ID_VERSION) {
e->type = ex_float;
e->e.float_val = e->e.integer_val;
}
@ -182,8 +182,8 @@ warning (expr_t *e, const char *fmt, ...)
string_t file = s_file;
int line = pr_source_line;
if (options.warn_error) {
options.warn_error = 0; // only want to do this once
if (options.warnings.promote) {
options.warnings.promote = 0; // only want to do this once
fprintf (stderr, "%s: warnings treated as errors\n", "qfcc");
pr_error_count++;
}
@ -249,7 +249,7 @@ type_mismatch (expr_t *e1, expr_t *e2, int op)
void
check_initialized (expr_t *e)
{
if (options.warn_uninitialized) {
if (options.warnings.uninited_variable) {
if (e->type == ex_def
&& !(e->e.def->type->type == ev_func && !e->e.def->scope)
&& !e->e.def->initialized) {
@ -781,7 +781,7 @@ test_expr (expr_t *e, int test)
case ev_integer:
return e;
case ev_float:
if (options.version == PROG_ID_VERSION)
if (options.code.progsversion == PROG_ID_VERSION)
return e;
new = new_expr ();
new->type = ex_float;
@ -930,7 +930,7 @@ type_mismatch:
type = t1;
}
if ((op >= OR && op <= GT) || op == '>' || op == '<') {
if (options.version > PROG_ID_VERSION)
if (options.code.progsversion > PROG_ID_VERSION)
type = &type_integer;
else
type = &type_float;
@ -1026,7 +1026,7 @@ unary_expr (int op, expr_t *e)
case ex_temp:
{
expr_t *n = new_unary_expr (op, e);
if (options.version > PROG_ID_VERSION)
if (options.code.progsversion > PROG_ID_VERSION)
n->e.expr.type = &type_integer;
else
n->e.expr.type = &type_float;

View file

@ -133,9 +133,9 @@ PR_Opcode_Init_Tables (void)
Hash_SetHashCompare (opcode_type_table_ab, get_hash, compare);
Hash_SetHashCompare (opcode_type_table_abc, get_hash, compare);
for (op = pr_opcodes; op->name; op++) {
if (op->min_version > options.version)
if (op->min_version > options.code.progsversion)
continue;
if (options.version == PROG_ID_VERSION
if (options.code.progsversion == PROG_ID_VERSION
&& op->type_c == ev_integer)
op->type_c = ev_float;
Hash_AddElement (opcode_type_table_ab, op);

View file

@ -246,7 +246,7 @@ type_or_name (char *token)
int i;
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
if (keywords[i].version <= options.version)
if (keywords[i].version <= options.code.progsversion)
Hash_Add (keyword_tab, &keywords[i]);
initialized = 1;
}

View file

@ -343,7 +343,7 @@ begin_function
$$ = current_func = new_function ();
$$->def = current_def;
$$->code = numstatements;
if (options.debug) {
if (options.code.debug) {
pr_lineno_t *lineno = new_lineno ();
$$->aux = new_auxfunction ();
$$->aux->source_line = pr_source_line;

View file

@ -4,7 +4,8 @@
QuakeForge Code Compiler (main program)
Copyright (C) 1996-1997 id Software, Inc.
Copyright (C) 2001 Jeff Teunissen <deek@dusknet.dhs.org>
Copyright (C) 2001 Jeff Teunissen <deek@quakeforge.net>
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -281,7 +282,7 @@ WriteData (int crc)
// PrintGlobals ();
strofs = (strofs + 3) & ~3;
if (options.quiet < 2) {
if (options.verbosity > 1) {
printf ("%6i strofs\n", strofs);
printf ("%6i statements\n", numstatements);
printf ("%6i functions\n", numfunctions);
@ -346,12 +347,12 @@ WriteData (int crc)
SafeWrite (h, pr_globals, numpr_globals * 4);
if (options.quiet < 2)
if (options.verbosity > 1)
printf ("%6i TOTAL SIZE\n", (int) ftell (h));
progs.entityfields = pr.size_fields;
progs.version = options.version;
progs.version = options.code.progsversion;
progs.crc = crc;
// byte swap the header and write it out
@ -362,7 +363,7 @@ WriteData (int crc)
SafeWrite (h, &progs, sizeof (progs));
fclose (h);
if (!options.debug) {
if (!options.code.debug) {
return;
}
@ -456,7 +457,6 @@ PR_String (char *string)
}
def_t *
PR_DefForFieldOfs (gofs_t ofs)
{
@ -704,7 +704,7 @@ PR_FinishCompilation (void)
expr_t e;
// check to make sure all functions prototyped have code
if (options.undefined_function_warning)
if (options.warnings.undefined_function)
for (d = pr.def_head.def_next; d; d = d->def_next) {
if (d->type->type == ev_func && !d->scope) { // function args ok
if (d->used) {
@ -719,7 +719,7 @@ PR_FinishCompilation (void)
if (errors)
return !errors;
if (options.debug) {
if (options.code.debug) {
e.type = ex_string;
e.e.string_val = debugfile;
PR_ReuseConstant (&e, PR_GetDef (&type_string, ".debug_file", 0,
@ -767,7 +767,7 @@ PR_WriteProgdefs (char *filename)
unsigned short crc;
int c;
if (!options.quiet)
if (options.verbosity)
printf ("writing %s\n", filename);
f = fopen (filename, "w");
@ -894,6 +894,38 @@ PR_PrintFunction (def_t *def)
}
}
/*
"Options: \n"
" -s, --source <dir> look for progs.src in directory <dir>\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" --cow allow assignment to initialized globals\n"
" --id only support id (progs version 6) features\n"
" --warn=error treat warnings as errors\n"
" --undefined-function-warning warn when a function isn't defined\n"
*/
qboolean
ParseParmOptions (const char *options, const char *name)
{
const char *start;
char *where, *terminator;
// Options are comma-separated, so bail if the string has a comma
if ((!(*name)) || strchr (name, ','))
return false;
for (start = options;; start = terminator) {
if (!(where = strstr (start, name)))
break;
terminator = where + strlen (name);
if ((where == start) || (*(where - 1) == ','))
if ((*terminator == ',') || (*terminator == '\0'))
return true;
}
return false;
}
//============================================================================
@ -916,11 +948,12 @@ main (int argc, char **argv)
myargc = argc;
myargv = argv;
options.version = PROG_VERSION;
options.warn_uninitialized = 1;
options.code.progsversion = PROG_VERSION;
options.warnings.uninited_variable = 1;
options.verbosity = 2;
if (CheckParm ("-h") || CheckParm ("--help")) {
printf ("%s - A compiler for the QuakeC language\n", argv[0]);
printf ("%s - QuakeForge Code Compiler\n", argv[0]);
printf ("Usage: %s [options]\n", argv[0]);
printf (
"Options: \n"
@ -929,8 +962,8 @@ main (int argc, char **argv)
" -V, --version output version information and exit\n"
" --cow allow assignment to initialized globals\n"
" --id only support id (progs version 6) features\n"
" --warn=error treat warnings as errors\n"
" --no-undefined-function-warning don't warn when a function isn't defined\n"
" --warn=error treat warnings as errors\n"
" --no-undefined-function-warning don't warn when a function isn't defined\n"
);
return 1;
}
@ -951,23 +984,24 @@ main (int argc, char **argv)
}
if (CheckParm ("--quiet=2")) { //FIXME: getopt, need getopt </#5>
options.quiet = 2;
options.verbosity = 0;
}
if (CheckParm ("--quiet")) {
options.quiet = 1;
options.verbosity = 1;
}
if (CheckParm ("--cow")) {
options.cow = 1;
options.code.cow = 1;
options.warnings.cow = 1;
}
if (CheckParm ("--id")) {
options.version = PROG_ID_VERSION;
options.code.progsversion = PROG_ID_VERSION;
}
if (CheckParm ("--debug")) {
options.debug = 1;
options.code.debug = 1;
}
if (CheckParm ("--no-cpp")) {
@ -976,12 +1010,16 @@ main (int argc, char **argv)
// FIXME eww, really must go to getopt
if (CheckParm ("--warn=error")) {
options.warn_error = 1;
options.warnings.promote = 1;
}
options.undefined_function_warning = 1;
if (CheckParm ("--warn=nocow")) {
options.warnings.cow = 0;
}
options.warnings.undefined_function = 1;
if (CheckParm ("--no-undefined-function-warning")) {
options.undefined_function_warning = 0;
options.warnings.undefined_function = 0;
}
if (strcmp (sourcedir, ".")) {
@ -999,10 +1037,10 @@ main (int argc, char **argv)
Error ("No destination filename. qfcc --help for info.\n");
strcpy (destfile, com_token);
if (!options.quiet) {
if (options.verbosity) {
printf ("outputfile: %s\n", destfile);
}
if (options.debug) {
if (options.code.debug) {
char *s;
strcpy (debugfile, com_token);
@ -1016,7 +1054,7 @@ main (int argc, char **argv)
}
}
strcpy (s, ".sym");
if (!options.quiet)
if (options.verbosity)
printf ("debug file: %s\n", debugfile);
}
@ -1032,14 +1070,16 @@ main (int argc, char **argv)
int tempfd;
#endif
int error;
extern FILE *yyin;
int yyparse(void);
int yyparse (void);
extern void clear_frame_macros (void);
//extern int yydebug;
//yydebug = 1;
sprintf (filename, "%s%c%s", sourcedir, PATH_SEPARATOR, com_token);
if (!options.quiet)
if (options.verbosity)
printf ("compiling %s\n", filename);
#ifdef USE_CPP
@ -1069,7 +1109,7 @@ main (int argc, char **argv)
int status;
pid_t rc;
// printf ("pid = %d\n", pid);
// printf ("pid = %d\n", pid);
if ((rc = waitpid (0, &status, 0 | WUNTRACED)) != pid) {
if (rc == -1) {
perror ("wait");
@ -1129,7 +1169,28 @@ main (int argc, char **argv)
WriteFiles ();
stop = Sys_DoubleTime ();
if (options.quiet < 2)
printf ("Compilation time: %.3f seconds.\n", (stop - start));
if (options.verbosity > 1)
printf ("Compilation time: %0.3g seconds.\n", (stop - start));
return 0;
}
/*
static void
usage (int status)
{
printf ("%s - the QuakeForge Code Compiler\n", PROGRAM);
printf ("Usage: %s [options]\n", argv[0]);
printf (
"Options:\n"
" -s, --source DIR look for progs.src in DIR instead of \".\"\n"
" -q, --quiet NUM Inhibit usual output\n"
" -g, --debug Output symbol information\n"
" --code=<option,...> Set code generation options\n"
" --warn=<option,...> Set warning options\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n\n"
"For help on options for --code and --warn, see the qfcc(1) man page\n"
);
exit (status);
}
*/