ok, structures seem to generate correct code now

This commit is contained in:
Bill Currie 2001-12-08 08:19:48 +00:00
parent 3293c5e85f
commit b03a1bee42
16 changed files with 236 additions and 34 deletions

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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:

View file

@ -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},

View file

@ -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

View file

@ -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,

View file

@ -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
{ {

View file

@ -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

View file

@ -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 ();
} }

View file

@ -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 ();

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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 *