mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
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:
parent
018b3ae536
commit
34ec521198
8 changed files with 77 additions and 25 deletions
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue