vararg functions can now be imlemented in qc using @argc (number of params

passed through ...) and @argv (array of vectors, one for each ... param)
This commit is contained in:
Bill Currie 2002-05-22 20:43:29 +00:00
parent 018b3ae536
commit 34ec521198
8 changed files with 77 additions and 25 deletions

View file

@ -209,12 +209,34 @@ PR_EnterFunction (progs_t * pr, dfunction_t *f)
// copy parameters
o = f->parm_start;
for (i = 0; i < f->numparms; i++) {
for (j = 0; j < f->parm_size[i]; j++) {
if (f->numparms >= 0) {
for (i = 0; i < f->numparms; i++) {
for (j = 0; j < f->parm_size[i]; j++) {
memcpy (&pr->pr_globals[o],
&pr->pr_globals[OFS_PARM0 + i * 3 + j],
sizeof (pr_type_t));
o++;
}
}
} else {
pr_type_t *argc = &pr->pr_globals[o++];
pr_type_t *argv = &pr->pr_globals[o++];
for (i = 0; i < -f->numparms - 1; i++) {
for (j = 0; j < f->parm_size[i]; j++) {
memcpy (&pr->pr_globals[o],
&pr->pr_globals[OFS_PARM0 + i * 3 + j],
sizeof (pr_type_t));
o++;
}
}
argc->integer_var = pr->pr_argc - i;
argv->integer_var = o;
while (i < MAX_PARMS) {
memcpy (&pr->pr_globals[o],
&pr->pr_globals[OFS_PARM0 + i * 3 + j],
sizeof (pr_type_t));
o++;
&pr->pr_globals[OFS_PARM0 + i * 3],
3);
o += 3;
i++;
}
}

View file

@ -66,6 +66,7 @@ type_t *find_type (type_t *new);
void new_typedef (const char *name, type_t *type);
type_t *get_typedef (const char *name);
type_t *pointer_type (type_t *aux);
type_t *array_type (type_t *aux, int size);
void print_type (type_t *type);
void encode_type (struct dstring_s *encodking, type_t *type);
int type_assignable (type_t *dst, type_t *src);

View file

@ -102,13 +102,23 @@ parse_params (type_t *type, param_t *parms)
void
build_scope (function_t *f, def_t *func, param_t *params)
{
int i;
def_t *def;
int i;
def_t *def;
param_t *p;
def_t *argv = 0;
func->alloc = &func->locals;
for (p = params, i = 0; p; p = p->next, i++) {
if (func->type->num_parms < 0) {
def = PR_GetDef (&type_integer, ".argc", func, func->alloc);
def->used = 1;
PR_DefInitialized (def);
argv = PR_GetDef (&type_pointer, ".argv", func, func->alloc);
argv->used = 1;
PR_DefInitialized (argv);
}
for (p = params, i = 0; p; p = p->next) {
if (!p->selector && !p->type && !p->name)
continue; // ellipsis marker
if (!p->type)
@ -120,6 +130,17 @@ build_scope (function_t *f, def_t *func, param_t *params)
//printf ("%s%s %d\n", p == params ? "" : " ", p->name, def->ofs);
def->used = 1; // don't warn for unused params
PR_DefInitialized (def); // params are assumed to be initialized
i++;
}
if (argv) {
while (i < MAX_PARMS) {
def = PR_GetDef (&type_vector, 0, func, func->alloc);
def->used = 1;
if (argv->type == &type_pointer)
argv->type = array_type (&type_vector, MAX_PARMS - i);
i++;
}
}
}

View file

@ -63,6 +63,8 @@ check_for_name (type_t *type, const char *name, def_t *scope, int *allocate)
if (!defs_by_name) {
defs_by_name = Hash_NewTable (16381, defs_get_key, 0, &defs_by_name);
}
if (!name)
return 0;
if (!scope && (find_struct (name) || get_enum (name))) {
error (0, "%s redeclared", name);
return 0;
@ -115,7 +117,8 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
// allocate a new def
def = PR_NewDef (type, name, scope);
Hash_Add (defs_by_name, def);
if (name)
Hash_Add (defs_by_name, def);
// FIXME: need to sort out location re-use
def->ofs = *allocate;
@ -125,7 +128,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
make automatic defs for the vectors elements .origin can be accessed
as .origin_x, .origin_y, and .origin_z
*/
if (type->type == ev_vector) {
if (type->type == ev_vector && name) {
def_t *d;
snprintf (element, sizeof (element), "%s_x", name);

View file

@ -279,6 +279,8 @@ static keyword_t keywords[] = {
{"@public", PUBLIC, 0, 0, PROG_VERSION},
{"@selector", SELECTOR, 0, 0, PROG_VERSION},
{"@self", SELF, 0, 0, PROG_VERSION},
{"@argc", ARGC, 0, 0, PROG_VERSION},
{"@argv", ARGV, 0, 0, PROG_VERSION},
};
static const char *

View file

@ -65,7 +65,6 @@ parse_error (void)
int yylex (void);
type_t *build_type (int is_field, type_t *type);
type_t *build_array_type (type_t *type, int size);
hashtab_t *save_local_inits (def_t *scope);
hashtab_t *merge_local_inits (hashtab_t *dl_1, hashtab_t *dl_2);
@ -114,6 +113,7 @@ void free_local_inits (hashtab_t *def_list);
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS NIL
%token IFBE IFB IFAE IFA
%token SWITCH CASE DEFAULT STRUCT ENUM TYPEDEF SUPER SELF
%token ARGC ARGV
%token ELE_START
%token <type> TYPE
@ -253,7 +253,7 @@ type
}
| non_field_type array_decl
{
$$ = build_type (0, build_array_type ($1, $2));
$$ = build_type (0, array_type ($1, $2));
}
;
@ -780,6 +780,8 @@ expr
| expr INCOP { $$ = incop_expr ($2, $1, 1); }
| obj_expr { $$ = $1; }
| NAME { $$ = new_name_expr ($1); }
| ARGC { $$ = new_name_expr (".argc"); }
| ARGV { $$ = new_name_expr (".argv"); }
| SELF { $$ = new_self_expr (); }
| const { $$ = $1; }
| '(' expr ')' { $$ = $2; $$->paren = 1; }
@ -1302,18 +1304,6 @@ build_type (int is_field, type_t *type)
}
}
type_t *
build_array_type (type_t *type, int size)
{
type_t new;
memset (&new, 0, sizeof (new));
new.type = ev_pointer;
new.aux_type = type;
new.num_parms = size;
return find_type (&new);
}
typedef struct {
def_t *def;
int state;

View file

@ -19,7 +19,7 @@ DEP=$(patsubst %.o,%.d,$(OBJ))
all: $(EXE) $(EXE).dat
$(EXE): $(OBJ) $(LIBS)
$(CC) $(LDFLAGS) -o $@ $^ -lQFgamecode -lQFutil -lz -lm
$(CC) $(LDFLAGS) -o $@ $^ ../../d.o/libs/gamecode/engine/.libs/libQFgamecode.a -lQFutil -lz -lm
$(EXE).dat: progs.src *.qc
qfcc --warn=error --code=debug

View file

@ -20,12 +20,25 @@ string [6] dot = {
"gfx/menudot5.lpm",
};
void (string fmt, ...) test_argv =
{
traceon ();
local vector v;
local integer i;
local string f = fmt;
for (i = 0; i < @argc; i++)
v = @argv[i];
traceoff ();
};
float () main =
{
local float messed_or;
local integer handle;
local string buffer;
test_argv ("hi there", 1, "123", '1', '1 2 3');
messed_or = PC_ENGINEER_TF_ITEMS;
handle = open ("main.qc", 0);
if (handle == -1) {