mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-16 17:01:53 +00:00
ok, structures seem to generate correct code now
This commit is contained in:
parent
3293c5e85f
commit
b03a1bee42
16 changed files with 236 additions and 34 deletions
|
@ -39,6 +39,7 @@ typedef enum {
|
||||||
ev_integer,
|
ev_integer,
|
||||||
ev_uinteger,
|
ev_uinteger,
|
||||||
ev_short, // value is embedded in the opcode
|
ev_short, // value is embedded in the opcode
|
||||||
|
ev_struct,
|
||||||
|
|
||||||
ev_type_count // not a type, gives number of types
|
ev_type_count // not a type, gives number of types
|
||||||
} etype_t;
|
} etype_t;
|
||||||
|
@ -236,6 +237,8 @@ typedef enum {
|
||||||
OP_STOREBI_FNC,
|
OP_STOREBI_FNC,
|
||||||
OP_STOREBI_I,
|
OP_STOREBI_I,
|
||||||
OP_STOREBI_P,
|
OP_STOREBI_P,
|
||||||
|
|
||||||
|
OP_LEAI,
|
||||||
} pr_opcode_e;
|
} pr_opcode_e;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -161,7 +161,7 @@ void ED_Count (progs_t *pr);
|
||||||
void PR_Profile (progs_t *pr);
|
void PR_Profile (progs_t *pr);
|
||||||
|
|
||||||
char *PR_GlobalString (progs_t *pr, int ofs, etype_t type);
|
char *PR_GlobalString (progs_t *pr, int ofs, etype_t type);
|
||||||
char *PR_GlobalStringNoContents (progs_t *pr, int ofs);
|
char *PR_GlobalStringNoContents (progs_t *pr, int ofs, etype_t type);
|
||||||
|
|
||||||
pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field);
|
pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ static const char rcsid[] =
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "QF/cmd.h"
|
#include "QF/cmd.h"
|
||||||
#include "compat.h"
|
|
||||||
#include "QF/crc.h"
|
#include "QF/crc.h"
|
||||||
#include "QF/cvar.h"
|
#include "QF/cvar.h"
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
|
@ -52,6 +51,8 @@ static const char rcsid[] =
|
||||||
#include "QF/va.h"
|
#include "QF/va.h"
|
||||||
#include "QF/vfs.h"
|
#include "QF/vfs.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
cvar_t *pr_boundscheck;
|
cvar_t *pr_boundscheck;
|
||||||
cvar_t *pr_deadbeef_ents;
|
cvar_t *pr_deadbeef_ents;
|
||||||
cvar_t *pr_deadbeef_locals;
|
cvar_t *pr_deadbeef_locals;
|
||||||
|
@ -69,6 +70,7 @@ int pr_type_size[ev_type_count] = {
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
0, // value in opcode
|
0, // value in opcode
|
||||||
|
1, // variable
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *type_name[ev_type_count] = {
|
const char *type_name[ev_type_count] = {
|
||||||
|
@ -84,6 +86,7 @@ const char *type_name[ev_type_count] = {
|
||||||
"integer",
|
"integer",
|
||||||
"uinteger",
|
"uinteger",
|
||||||
"short",
|
"short",
|
||||||
|
"struct",
|
||||||
};
|
};
|
||||||
|
|
||||||
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
|
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
|
||||||
|
@ -512,12 +515,16 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
PR_GlobalStringNoContents (progs_t * pr, int ofs)
|
PR_GlobalStringNoContents (progs_t * pr, int ofs, etype_t type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
ddef_t *def = 0;
|
ddef_t *def = 0;
|
||||||
static char line[128];
|
static char line[128];
|
||||||
|
|
||||||
|
if (type == ev_short) {
|
||||||
|
snprintf (line, sizeof (line), "%-20d", (short) ofs);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
if (pr_debug->int_val && pr->debug)
|
if (pr_debug->int_val && pr->debug)
|
||||||
def = PR_Get_Local_Def (pr, ofs);
|
def = PR_Get_Local_Def (pr, ofs);
|
||||||
if (!def)
|
if (!def)
|
||||||
|
|
|
@ -86,13 +86,15 @@ PR_PrintStatement (progs_t * pr, dstatement_t *s)
|
||||||
if (op->type_c != ev_void)
|
if (op->type_c != ev_void)
|
||||||
Sys_Printf ("%s", PR_GlobalString (pr, s->b, op->type_b));
|
Sys_Printf ("%s", PR_GlobalString (pr, s->b, op->type_b));
|
||||||
else
|
else
|
||||||
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->b));
|
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->b,
|
||||||
|
op->type_b));
|
||||||
}
|
}
|
||||||
if (op->type_c != ev_void) {
|
if (op->type_c != ev_void) {
|
||||||
if (op->type_b == ev_pointer && op->type_c == ev_integer)
|
if (op->type_b == ev_pointer && op->type_c == ev_integer)
|
||||||
Sys_Printf ("%s", PR_GlobalString (pr, s->c, op->type_c));
|
Sys_Printf ("%s", PR_GlobalString (pr, s->c, op->type_c));
|
||||||
else
|
else
|
||||||
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c));
|
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c,
|
||||||
|
op->type_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sys_Printf ("\n");
|
Sys_Printf ("\n");
|
||||||
|
@ -598,6 +600,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
OPC.integer_var = pointer;
|
OPC.integer_var = pointer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_LEAI:
|
||||||
|
pointer = OPA.integer_var + (short) st->b;
|
||||||
|
OPC.integer_var = pointer;
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_STOREB_F:
|
case OP_STOREB_F:
|
||||||
case OP_STOREB_S:
|
case OP_STOREB_S:
|
||||||
case OP_STOREB_ENT:
|
case OP_STOREB_ENT:
|
||||||
|
|
|
@ -121,7 +121,8 @@ opcode_t pr_opcodes[] = {
|
||||||
{"&", "address.i", OP_ADDRESS_I, false, ev_integer, ev_void, ev_pointer, PROG_VERSION},
|
{"&", "address.i", OP_ADDRESS_I, false, ev_integer, ev_void, ev_pointer, PROG_VERSION},
|
||||||
{"&", "address.p", OP_ADDRESS_P, false, ev_pointer, ev_void, ev_pointer, PROG_VERSION},
|
{"&", "address.p", OP_ADDRESS_P, false, ev_pointer, ev_void, ev_pointer, PROG_VERSION},
|
||||||
|
|
||||||
{"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
|
{"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION},
|
||||||
|
{"&", "leai", OP_LEAI, false, ev_pointer, ev_short, ev_pointer, PROG_VERSION},
|
||||||
|
|
||||||
{"=", "store.f", OP_STORE_F, true, ev_float, ev_float, ev_void, PROG_ID_VERSION},
|
{"=", "store.f", OP_STORE_F, true, ev_float, ev_float, ev_void, PROG_ID_VERSION},
|
||||||
{"=", "store.v", OP_STORE_V, true, ev_vector, ev_vector, ev_void, PROG_ID_VERSION},
|
{"=", "store.v", OP_STORE_V, true, ev_vector, ev_vector, ev_void, PROG_ID_VERSION},
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
gcc -o GLstub.so -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c
|
gcc -o GLstub.so -fPIC -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c
|
||||||
|
|
|
@ -6,6 +6,7 @@ typedef enum {
|
||||||
ex_def,
|
ex_def,
|
||||||
ex_temp, // temporary variable
|
ex_temp, // temporary variable
|
||||||
ex_nil, // umm, nil, null. nuff said
|
ex_nil, // umm, nil, null. nuff said
|
||||||
|
ex_name,
|
||||||
|
|
||||||
ex_string,
|
ex_string,
|
||||||
ex_float,
|
ex_float,
|
||||||
|
|
|
@ -283,10 +283,13 @@ typedef struct type_s
|
||||||
etype_t type;
|
etype_t type;
|
||||||
struct def_s *def; // a def that points to this type
|
struct def_s *def; // a def that points to this type
|
||||||
struct type_s *next;
|
struct type_s *next;
|
||||||
// function types are more complex
|
// function/pointer/struct types are more complex
|
||||||
struct type_s *aux_type; // return type or field type
|
struct type_s *aux_type; // return type or field type
|
||||||
int num_parms; // -1 = variable args
|
int num_parms; // -1 = variable args
|
||||||
struct type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
|
struct type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
|
||||||
|
struct hashtab_s *struct_fields;
|
||||||
|
struct struct_field_s *struct_head;
|
||||||
|
struct struct_field_s **struct_tail;
|
||||||
} type_t;
|
} type_t;
|
||||||
|
|
||||||
typedef struct statref_s {
|
typedef struct statref_s {
|
||||||
|
@ -359,6 +362,7 @@ extern type_t type_quaternion;
|
||||||
extern type_t type_integer;
|
extern type_t type_integer;
|
||||||
extern type_t type_uinteger;
|
extern type_t type_uinteger;
|
||||||
extern type_t type_short;
|
extern type_t type_short;
|
||||||
|
extern type_t type_struct;
|
||||||
|
|
||||||
extern def_t def_void;
|
extern def_t def_void;
|
||||||
extern def_t def_string;
|
extern def_t def_string;
|
||||||
|
@ -372,6 +376,7 @@ extern def_t def_quaternion;
|
||||||
extern def_t def_integer;
|
extern def_t def_integer;
|
||||||
extern def_t def_uinteger;
|
extern def_t def_uinteger;
|
||||||
extern def_t def_short;
|
extern def_t def_short;
|
||||||
|
extern def_t def_struct;
|
||||||
|
|
||||||
struct function_s
|
struct function_s
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,5 +33,5 @@ YFLAGS = -d
|
||||||
|
|
||||||
bin_PROGRAMS= qfcc
|
bin_PROGRAMS= qfcc
|
||||||
|
|
||||||
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c switch.c getopt.c getopt1.c
|
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c struct.c switch.c getopt.c getopt1.c
|
||||||
qfcc_LDADD= -lQFgamecode -lQFutil
|
qfcc_LDADD= -lQFgamecode -lQFutil
|
||||||
|
|
|
@ -77,6 +77,8 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b,
|
||||||
if (op->type_c == ev_void) {
|
if (op->type_c == ev_void) {
|
||||||
var_c = NULL;
|
var_c = NULL;
|
||||||
statement->c = 0;
|
statement->c = 0;
|
||||||
|
} else {
|
||||||
|
statement->c = var_c->ofs;
|
||||||
}
|
}
|
||||||
ret = var_a;
|
ret = var_a;
|
||||||
} else { // allocate result space
|
} else { // allocate result space
|
||||||
|
@ -249,6 +251,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
||||||
emit_expr (e);
|
emit_expr (e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ex_name:
|
||||||
case ex_nil:
|
case ex_nil:
|
||||||
case ex_label:
|
case ex_label:
|
||||||
error (e, "internal error");
|
error (e, "internal error");
|
||||||
|
@ -299,6 +302,24 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
||||||
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||||
dest->users += 2;
|
dest->users += 2;
|
||||||
}
|
}
|
||||||
|
} else if (e->e.expr.op == '&') {
|
||||||
|
static expr_t zero;
|
||||||
|
def_t *tmp = 0;
|
||||||
|
|
||||||
|
zero.type = ex_short;
|
||||||
|
|
||||||
|
operator = "&";
|
||||||
|
if (e->e.expr.e1->type == ex_expr
|
||||||
|
&& e->e.expr.e1->e.expr.op == '.') {
|
||||||
|
tmp = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||||
|
tmp->users += 2;
|
||||||
|
}
|
||||||
|
def_a = emit_sub_expr (e->e.expr.e1, tmp);
|
||||||
|
def_b = emit_sub_expr (&zero, 0);
|
||||||
|
if (!dest) {
|
||||||
|
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||||
|
dest->users += 2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
@ -335,6 +356,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
||||||
d = PR_NewDef (&type_short, 0, pr_scope);
|
d = PR_NewDef (&type_short, 0, pr_scope);
|
||||||
d->ofs = e->e.short_val;
|
d->ofs = e->e.short_val;
|
||||||
d->absolute = 1;
|
d->absolute = 1;
|
||||||
|
d->users = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PR_FreeTempDefs ();
|
PR_FreeTempDefs ();
|
||||||
|
@ -454,6 +476,7 @@ emit_expr (expr_t *e)
|
||||||
warning (e, "Ignoring useless expression");
|
warning (e, "Ignoring useless expression");
|
||||||
break;
|
break;
|
||||||
case ex_nil:
|
case ex_nil:
|
||||||
|
case ex_name:
|
||||||
error (e, "internal error");
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ static const char rcsid[] =
|
||||||
|
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
#include "struct.h"
|
||||||
#include "qc-parse.h"
|
#include "qc-parse.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ etype_t qc_types[] = {
|
||||||
ev_void, // ex_def
|
ev_void, // ex_def
|
||||||
ev_void, // ex_temp
|
ev_void, // ex_temp
|
||||||
ev_void, // ex_nil
|
ev_void, // ex_nil
|
||||||
|
ev_void, // ex_name
|
||||||
|
|
||||||
ev_string, // ex_string
|
ev_string, // ex_string
|
||||||
ev_float, // ex_float
|
ev_float, // ex_float
|
||||||
|
@ -93,13 +95,31 @@ expr_type expr_types[] = {
|
||||||
ex_integer, // ev_integer
|
ex_integer, // ev_integer
|
||||||
ex_uinteger, // ev_uinteger
|
ex_uinteger, // ev_uinteger
|
||||||
ex_short, // ev_short
|
ex_short, // ev_short
|
||||||
|
ex_nil, // ev_struct FIXME???
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
convert_name (expr_t *e)
|
||||||
|
{
|
||||||
|
if (e->type == ex_name) {
|
||||||
|
const char * name = e->e.string_val;
|
||||||
|
|
||||||
|
e->type = ex_def;
|
||||||
|
e->e.def = PR_GetDef (NULL, name, pr_scope, false);
|
||||||
|
if (!e->e.def) {
|
||||||
|
error (e, "Undeclared variable \"%s\".", name);
|
||||||
|
e->e.def = &def_float;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type_t *
|
type_t *
|
||||||
get_type (expr_t *e)
|
get_type (expr_t *e)
|
||||||
{
|
{
|
||||||
|
convert_name (e);
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
case ex_name:
|
||||||
return 0; // something went very wrong
|
return 0; // something went very wrong
|
||||||
case ex_nil:
|
case ex_nil:
|
||||||
return &type_void;
|
return &type_void;
|
||||||
|
@ -487,6 +507,7 @@ print_expr (expr_t *e)
|
||||||
printf ("NULL");
|
printf ("NULL");
|
||||||
break;
|
break;
|
||||||
case ex_string:
|
case ex_string:
|
||||||
|
case ex_name:
|
||||||
printf ("\"%s\"", e->e.string_val);
|
printf ("\"%s\"", e->e.string_val);
|
||||||
break;
|
break;
|
||||||
case ex_float:
|
case ex_float:
|
||||||
|
@ -798,8 +819,36 @@ field_expr (expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
etype_t t1, t2;
|
etype_t t1, t2;
|
||||||
expr_t *e;
|
expr_t *e;
|
||||||
|
type_t *strct;
|
||||||
|
struct_field_t *field;
|
||||||
|
|
||||||
t1 = extract_type (e1);
|
t1 = extract_type (e1);
|
||||||
|
if (t1 == ev_struct) {
|
||||||
|
strct = get_type (e1);
|
||||||
|
if (e2->type != ex_name)
|
||||||
|
return error (e2, "structure field name expected");
|
||||||
|
field = struct_find_field (strct, e2->e.string_val);
|
||||||
|
if (!field)
|
||||||
|
return error (e2, "structure has no field %s", e2->e.string_val);
|
||||||
|
e2->type = ex_short;
|
||||||
|
e2->e.short_val = field->offset;
|
||||||
|
e = new_binary_expr ('.', unary_expr ('&', e1), e2);
|
||||||
|
e->e.expr.type = field->type;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
if (t1 == ev_pointer
|
||||||
|
&& (strct = get_type(e1)->aux_type)->type == ev_struct) {
|
||||||
|
if (e2->type != ex_name)
|
||||||
|
return error (e2, "structure field name expected");
|
||||||
|
field = struct_find_field (strct, e2->e.string_val);
|
||||||
|
if (!field)
|
||||||
|
return error (e2, "structure has no field %s", e2->e.string_val);
|
||||||
|
e2->type = ex_short;
|
||||||
|
e2->e.short_val = field->offset;
|
||||||
|
e = new_binary_expr ('.', e1, e2);
|
||||||
|
e->e.expr.type = field->type;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
t2 = extract_type (e2);
|
t2 = extract_type (e2);
|
||||||
|
|
||||||
if ((t1 != ev_entity || t2 != ev_field)
|
if ((t1 != ev_entity || t2 != ev_field)
|
||||||
|
@ -831,8 +880,7 @@ test_expr (expr_t *e, int test)
|
||||||
error (e, "internal error");
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
case ev_void:
|
case ev_void:
|
||||||
error (e, "void has no value");
|
return error (e, "void has no value");
|
||||||
break;
|
|
||||||
case ev_string:
|
case ev_string:
|
||||||
new = new_expr ();
|
new = new_expr ();
|
||||||
new->type = ex_string;
|
new->type = ex_string;
|
||||||
|
@ -871,6 +919,8 @@ test_expr (expr_t *e, int test)
|
||||||
new = new_expr ();
|
new = new_expr ();
|
||||||
new->type = ex_quaternion;
|
new->type = ex_quaternion;
|
||||||
break;
|
break;
|
||||||
|
case ev_struct:
|
||||||
|
return error (e, "struct cannot be tested");
|
||||||
}
|
}
|
||||||
new->line = e->line;
|
new->line = e->line;
|
||||||
new->file = e->file;
|
new->file = e->file;
|
||||||
|
@ -894,9 +944,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
type_t *type = 0;
|
type_t *type = 0;
|
||||||
expr_t *e;
|
expr_t *e;
|
||||||
|
|
||||||
|
convert_name (e1);
|
||||||
if (op != '=')
|
if (op != '=')
|
||||||
check_initialized (e1);
|
check_initialized (e1);
|
||||||
check_initialized (e2);
|
|
||||||
|
|
||||||
if (op == '=' && e1->type == ex_def)
|
if (op == '=' && e1->type == ex_def)
|
||||||
PR_DefInitialized (e1->e.def);
|
PR_DefInitialized (e1->e.def);
|
||||||
|
@ -911,6 +961,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
if (op == '.')
|
if (op == '.')
|
||||||
return field_expr (e1, e2);
|
return field_expr (e1, e2);
|
||||||
|
|
||||||
|
convert_name (e2);
|
||||||
|
check_initialized (e2);
|
||||||
|
|
||||||
if (op == OR || op == AND) {
|
if (op == OR || op == AND) {
|
||||||
e1 = test_expr (e1, true);
|
e1 = test_expr (e1, true);
|
||||||
e2 = test_expr (e2, true);
|
e2 = test_expr (e2, true);
|
||||||
|
@ -1028,11 +1081,13 @@ asx_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
expr_t *
|
expr_t *
|
||||||
unary_expr (int op, expr_t *e)
|
unary_expr (int op, expr_t *e)
|
||||||
{
|
{
|
||||||
|
convert_name (e);
|
||||||
check_initialized (e);
|
check_initialized (e);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case '-':
|
case '-':
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
case ex_name:
|
||||||
error (e, "internal error");
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
|
@ -1084,6 +1139,8 @@ unary_expr (int op, expr_t *e)
|
||||||
case '!':
|
case '!':
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
case ex_name:
|
||||||
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
case ex_block:
|
case ex_block:
|
||||||
if (!e->e.block.result)
|
if (!e->e.block.result)
|
||||||
|
@ -1142,13 +1199,15 @@ unary_expr (int op, expr_t *e)
|
||||||
case '~':
|
case '~':
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
case ex_name:
|
||||||
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (e->e.expr.op == '~')
|
if (e->e.expr.op == '~')
|
||||||
return e->e.expr.e1;
|
return e->e.expr.e1;
|
||||||
case ex_block:
|
case ex_block:
|
||||||
if (!e->e.block.result)
|
if (!e->e.block.result)
|
||||||
return error (e, "invalid type for unary -");
|
return error (e, "invalid type for unary ~");
|
||||||
case ex_expr:
|
case ex_expr:
|
||||||
case ex_def:
|
case ex_def:
|
||||||
case ex_temp:
|
case ex_temp:
|
||||||
|
@ -1183,8 +1242,54 @@ unary_expr (int op, expr_t *e)
|
||||||
return error (e, "invalid type for unary ~");
|
return error (e, "invalid type for unary ~");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
case '&':
|
||||||
abort ();
|
switch (e->type) {
|
||||||
|
case ex_label:
|
||||||
|
case ex_name:
|
||||||
|
error (e, "internal error");
|
||||||
|
abort ();
|
||||||
|
case ex_def:
|
||||||
|
{
|
||||||
|
type_t new;
|
||||||
|
expr_t *n = new_unary_expr (op, e);
|
||||||
|
|
||||||
|
memset (&new, 0, sizeof (new));
|
||||||
|
new.type = ev_pointer;
|
||||||
|
new.aux_type = e->e.def->type;
|
||||||
|
n->e.expr.type = PR_FindType (&new);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
case ex_expr:
|
||||||
|
if (e->e.expr.op == '.') {
|
||||||
|
expr_t *e1 = e->e.expr.e1;
|
||||||
|
if (get_type (e1) == &type_entity) {
|
||||||
|
type_t new;
|
||||||
|
|
||||||
|
memset (&new, 0, sizeof (new));
|
||||||
|
new.type = ev_pointer;
|
||||||
|
new.aux_type = e->e.expr.type;
|
||||||
|
e->e.expr.type = PR_FindType (&new);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ex_uexpr:
|
||||||
|
case ex_block:
|
||||||
|
case ex_temp:
|
||||||
|
case ex_short:
|
||||||
|
case ex_integer:
|
||||||
|
case ex_uinteger:
|
||||||
|
case ex_float:
|
||||||
|
case ex_nil:
|
||||||
|
case ex_string:
|
||||||
|
case ex_vector:
|
||||||
|
case ex_quaternion:
|
||||||
|
case ex_entity:
|
||||||
|
case ex_field:
|
||||||
|
case ex_func:
|
||||||
|
case ex_pointer:
|
||||||
|
return error (e, "invalid type for unary &");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
error (e, "internal error");
|
error (e, "internal error");
|
||||||
abort ();
|
abort ();
|
||||||
|
|
|
@ -102,6 +102,14 @@ PR_GetArray (type_t *etype, const char *name, int size, def_t *scope,
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PR_GetTypeSize (type_t *type)
|
||||||
|
{
|
||||||
|
if (type->type == ev_struct)
|
||||||
|
return type->num_parms;
|
||||||
|
return pr_type_size[type->type];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PR_GetDef
|
PR_GetDef
|
||||||
|
|
||||||
|
@ -113,6 +121,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||||
{
|
{
|
||||||
def_t *def = check_for_name (type, name, scope, allocate);
|
def_t *def = check_for_name (type, name, scope, allocate);
|
||||||
char element[MAX_NAME];
|
char element[MAX_NAME];
|
||||||
|
int size;
|
||||||
|
|
||||||
if (def || !allocate)
|
if (def || !allocate)
|
||||||
return def;
|
return def;
|
||||||
|
@ -147,7 +156,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||||
d->used = 1;
|
d->used = 1;
|
||||||
d->parent = def;
|
d->parent = def;
|
||||||
} else {
|
} else {
|
||||||
*allocate += pr_type_size[type->type];
|
*allocate += PR_GetTypeSize(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->type == ev_field) {
|
if (type->type == ev_field) {
|
||||||
|
@ -171,13 +180,15 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||||
d->used = 1; // always `used'
|
d->used = 1; // always `used'
|
||||||
d->parent = def;
|
d->parent = def;
|
||||||
} else if (type->aux_type->type == ev_pointer) {
|
} else if (type->aux_type->type == ev_pointer) {
|
||||||
pr.size_fields += type->aux_type->num_parms
|
size = PR_GetTypeSize (type->aux_type->aux_type);
|
||||||
* pr_type_size[type->aux_type->aux_type->type];
|
pr.size_fields += type->aux_type->num_parms * size;
|
||||||
} else {
|
} else {
|
||||||
pr.size_fields += pr_type_size[type->aux_type->type];
|
size = PR_GetTypeSize (type->aux_type);
|
||||||
|
pr.size_fields += size;
|
||||||
}
|
}
|
||||||
} else if (type->type == ev_pointer) {
|
} else if (type->type == ev_pointer) {
|
||||||
*allocate += type->num_parms * pr_type_size[type->aux_type->type];
|
size = PR_GetTypeSize (type->aux_type);
|
||||||
|
*allocate += type->num_parms * size;
|
||||||
def->initialized = def->constant = 1;
|
def->initialized = def->constant = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ type_t type_quaternion = { ev_quaternion, &def_quaternion };
|
||||||
type_t type_integer = { ev_integer, &def_integer };
|
type_t type_integer = { ev_integer, &def_integer };
|
||||||
type_t type_uinteger = { ev_uinteger, &def_uinteger };
|
type_t type_uinteger = { ev_uinteger, &def_uinteger };
|
||||||
type_t type_short = { ev_short, &def_short };
|
type_t type_short = { ev_short, &def_short };
|
||||||
|
type_t type_struct = { ev_struct, &def_struct };
|
||||||
|
|
||||||
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
|
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
|
||||||
|
|
||||||
|
@ -83,6 +84,7 @@ def_t def_quaternion = { &type_quaternion, "temp" };
|
||||||
def_t def_integer = { &type_integer, "temp" };
|
def_t def_integer = { &type_integer, "temp" };
|
||||||
def_t def_uinteger = { &type_uinteger, "temp" };
|
def_t def_uinteger = { &type_uinteger, "temp" };
|
||||||
def_t def_short = { &type_short, "temp" };
|
def_t def_short = { &type_short, "temp" };
|
||||||
|
def_t def_struct = { &type_struct, "temp" };
|
||||||
|
|
||||||
def_t def_ret, def_parms[MAX_PARMS];
|
def_t def_ret, def_parms[MAX_PARMS];
|
||||||
|
|
||||||
|
@ -304,8 +306,7 @@ PR_FindType (type_t *type)
|
||||||
|
|
||||||
// allocate a generic def for the type, so fields can reference it
|
// allocate a generic def for the type, so fields can reference it
|
||||||
def = malloc (sizeof (def_t));
|
def = malloc (sizeof (def_t));
|
||||||
|
if (!def)
|
||||||
if (!check)
|
|
||||||
Sys_Error ("PR_FindType: Memory Allocation Failure\n");
|
Sys_Error ("PR_FindType: Memory Allocation Failure\n");
|
||||||
def->name = "COMPLEX TYPE";
|
def->name = "COMPLEX TYPE";
|
||||||
def->type = check;
|
def->type = check;
|
||||||
|
|
|
@ -35,6 +35,7 @@ static const char rcsid[] =
|
||||||
#include <QF/sys.h>
|
#include <QF/sys.h>
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
#include "struct.h"
|
||||||
#include "qc-parse.h"
|
#include "qc-parse.h"
|
||||||
|
|
||||||
#define YY_NO_UNPUT
|
#define YY_NO_UNPUT
|
||||||
|
@ -227,6 +228,7 @@ static keyword_t keywords[] = {
|
||||||
{"case", CASE, 0, PROG_ID_VERSION},
|
{"case", CASE, 0, PROG_ID_VERSION},
|
||||||
{"default", DEFAULT, 0, PROG_ID_VERSION},
|
{"default", DEFAULT, 0, PROG_ID_VERSION},
|
||||||
{"NIL", NIL, 0, PROG_ID_VERSION},
|
{"NIL", NIL, 0, PROG_ID_VERSION},
|
||||||
|
{"struct", STRUCT, 0, PROG_VERSION},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -238,23 +240,27 @@ keyword_get_key (void *kw, void *unused)
|
||||||
int
|
int
|
||||||
type_or_name (char *token)
|
type_or_name (char *token)
|
||||||
{
|
{
|
||||||
static int initialized = 0;
|
|
||||||
static hashtab_t *keyword_tab;
|
static hashtab_t *keyword_tab;
|
||||||
keyword_t *keyword;
|
keyword_t *keyword;
|
||||||
|
type_t *type;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!keyword_tab) {
|
||||||
int i;
|
int i;
|
||||||
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
|
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
|
||||||
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
|
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
|
||||||
if (keywords[i].version <= options.code.progsversion)
|
if (keywords[i].version <= options.code.progsversion)
|
||||||
Hash_Add (keyword_tab, &keywords[i]);
|
Hash_Add (keyword_tab, &keywords[i]);
|
||||||
initialized = 1;
|
|
||||||
}
|
}
|
||||||
keyword = Hash_Find (keyword_tab, token);
|
keyword = Hash_Find (keyword_tab, token);
|
||||||
if (keyword) {
|
if (keyword) {
|
||||||
yylval.type = keyword->type;
|
yylval.type = keyword->type;
|
||||||
return keyword->value;
|
return keyword->value;
|
||||||
}
|
}
|
||||||
|
type = find_struct (token);
|
||||||
|
if (type) {
|
||||||
|
yylval.type = type;
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
yylval.string_val = strdup (token);
|
yylval.string_val = strdup (token);
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ static const char rcsid[] =
|
||||||
#include <QF/hash.h>
|
#include <QF/hash.h>
|
||||||
#include <QF/sys.h>
|
#include <QF/sys.h>
|
||||||
|
|
||||||
|
#include "struct.h"
|
||||||
#include "switch.h"
|
#include "switch.h"
|
||||||
|
|
||||||
#define YYDEBUG 1
|
#define YYDEBUG 1
|
||||||
|
@ -110,7 +111,7 @@ typedef struct {
|
||||||
|
|
||||||
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
|
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
|
||||||
%token IFBE IFB IFAE IFA
|
%token IFBE IFB IFAE IFA
|
||||||
%token SWITCH CASE DEFAULT
|
%token SWITCH CASE DEFAULT STRUCT
|
||||||
%token <type> TYPE
|
%token <type> TYPE
|
||||||
|
|
||||||
%type <type> type opt_func func_parms array_decl
|
%type <type> type opt_func func_parms array_decl
|
||||||
|
@ -137,6 +138,7 @@ expr_t *local_expr;
|
||||||
expr_t *break_label;
|
expr_t *break_label;
|
||||||
expr_t *continue_label;
|
expr_t *continue_label;
|
||||||
switch_block_t *switch_block;
|
switch_block_t *switch_block;
|
||||||
|
type_t *struct_type;
|
||||||
|
|
||||||
def_t *pr_scope; // the function being parsed, or NULL
|
def_t *pr_scope; // the function being parsed, or NULL
|
||||||
string_t s_file; // filename for function definition
|
string_t s_file; // filename for function definition
|
||||||
|
@ -157,6 +159,22 @@ def
|
||||||
{ current_type = build_type ($1, $4); } var_def_list
|
{ current_type = build_type ($1, $4); } var_def_list
|
||||||
| opt_field TYPE { current_type = $2; } func_parms
|
| opt_field TYPE { current_type = $2; } func_parms
|
||||||
{ current_type = build_type ($1, $4); } func_def_list
|
{ current_type = build_type ($1, $4); } func_def_list
|
||||||
|
| STRUCT NAME
|
||||||
|
{ struct_type = new_struct ($2); } '=' '{' struct_defs '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_defs
|
||||||
|
: /* empty */
|
||||||
|
| struct_defs struct_def ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_def
|
||||||
|
: opt_field TYPE
|
||||||
|
{ current_type = build_type ($1, $2); } struct_def_list
|
||||||
|
| opt_field TYPE { current_type = $2; } array_decl
|
||||||
|
{ current_type = build_type ($1, $4); } struct_def_list
|
||||||
|
| opt_field TYPE { current_type = $2; } func_parms
|
||||||
|
{ current_type = build_type ($1, $4); } struct_def_list
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_field
|
opt_field
|
||||||
|
@ -218,6 +236,15 @@ array_decl
|
||||||
| '[' ']' { $$ = build_array_type (0); }
|
| '[' ']' { $$ = build_array_type (0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
struct_def_list
|
||||||
|
: struct_def_list ',' struct_def_item
|
||||||
|
| struct_def_item
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_def_item
|
||||||
|
: NAME { new_struct_field (struct_type, current_type, $1); }
|
||||||
|
;
|
||||||
|
|
||||||
var_def_list
|
var_def_list
|
||||||
: var_def_list ',' var_def_item
|
: var_def_list ',' var_def_item
|
||||||
| var_def_item
|
| var_def_item
|
||||||
|
@ -683,12 +710,8 @@ expr
|
||||||
| NAME
|
| NAME
|
||||||
{
|
{
|
||||||
$$ = new_expr ();
|
$$ = new_expr ();
|
||||||
$$->type = ex_def;
|
$$->type = ex_name;
|
||||||
$$->e.def = PR_GetDef (NULL, $1, pr_scope, false);
|
$$->e.string_val = $1;
|
||||||
if (!$$->e.def) {
|
|
||||||
error (0, "Undeclared variable \"%s\".", $1);
|
|
||||||
$$->e.def = &def_float;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
| const { $$ = $1; }
|
| const { $$ = $1; }
|
||||||
| '(' expr ')' { $$ = $2; $$->paren = 1; }
|
| '(' expr ')' { $$ = $2; $$->paren = 1; }
|
||||||
|
@ -805,6 +828,14 @@ build_type (int is_field, type_t *type)
|
||||||
new.type = ev_field;
|
new.type = ev_field;
|
||||||
new.aux_type = type;
|
new.aux_type = type;
|
||||||
return PR_FindType (&new);
|
return PR_FindType (&new);
|
||||||
|
} else if (type->type == ev_struct) {
|
||||||
|
type_t new;
|
||||||
|
|
||||||
|
memset (&new, 0, sizeof (new));
|
||||||
|
new.type = ev_pointer;
|
||||||
|
new.aux_type = type;
|
||||||
|
new.num_parms = 1;
|
||||||
|
return PR_FindType (&new);
|
||||||
} else {
|
} else {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ new_struct_field (type_t *strct, type_t *type, const char *name)
|
||||||
field->next = 0;
|
field->next = 0;
|
||||||
*strct->struct_tail = field;
|
*strct->struct_tail = field;
|
||||||
strct->struct_tail = &field->next;
|
strct->struct_tail = &field->next;
|
||||||
return 0;
|
Hash_Add (strct->struct_fields, field);
|
||||||
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_field_t *
|
struct_field_t *
|
||||||
|
|
Loading…
Reference in a new issue