mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +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_uinteger,
|
||||
ev_short, // value is embedded in the opcode
|
||||
ev_struct,
|
||||
|
||||
ev_type_count // not a type, gives number of types
|
||||
} etype_t;
|
||||
|
@ -236,6 +237,8 @@ typedef enum {
|
|||
OP_STOREBI_FNC,
|
||||
OP_STOREBI_I,
|
||||
OP_STOREBI_P,
|
||||
|
||||
OP_LEAI,
|
||||
} pr_opcode_e;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -161,7 +161,7 @@ void ED_Count (progs_t *pr);
|
|||
void PR_Profile (progs_t *pr);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ static const char rcsid[] =
|
|||
#include <stdio.h>
|
||||
|
||||
#include "QF/cmd.h"
|
||||
#include "compat.h"
|
||||
#include "QF/crc.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/hash.h"
|
||||
|
@ -52,6 +51,8 @@ static const char rcsid[] =
|
|||
#include "QF/va.h"
|
||||
#include "QF/vfs.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
cvar_t *pr_boundscheck;
|
||||
cvar_t *pr_deadbeef_ents;
|
||||
cvar_t *pr_deadbeef_locals;
|
||||
|
@ -69,6 +70,7 @@ int pr_type_size[ev_type_count] = {
|
|||
1,
|
||||
1,
|
||||
0, // value in opcode
|
||||
1, // variable
|
||||
};
|
||||
|
||||
const char *type_name[ev_type_count] = {
|
||||
|
@ -84,6 +86,7 @@ const char *type_name[ev_type_count] = {
|
|||
"integer",
|
||||
"uinteger",
|
||||
"short",
|
||||
"struct",
|
||||
};
|
||||
|
||||
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
|
||||
|
@ -512,12 +515,16 @@ PR_GlobalString (progs_t * pr, int ofs, etype_t type)
|
|||
}
|
||||
|
||||
char *
|
||||
PR_GlobalStringNoContents (progs_t * pr, int ofs)
|
||||
PR_GlobalStringNoContents (progs_t * pr, int ofs, etype_t type)
|
||||
{
|
||||
int i;
|
||||
ddef_t *def = 0;
|
||||
static char line[128];
|
||||
|
||||
if (type == ev_short) {
|
||||
snprintf (line, sizeof (line), "%-20d", (short) ofs);
|
||||
return line;
|
||||
}
|
||||
if (pr_debug->int_val && pr->debug)
|
||||
def = PR_Get_Local_Def (pr, ofs);
|
||||
if (!def)
|
||||
|
|
|
@ -86,13 +86,15 @@ PR_PrintStatement (progs_t * pr, dstatement_t *s)
|
|||
if (op->type_c != ev_void)
|
||||
Sys_Printf ("%s", PR_GlobalString (pr, s->b, op->type_b));
|
||||
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_b == ev_pointer && op->type_c == ev_integer)
|
||||
Sys_Printf ("%s", PR_GlobalString (pr, s->c, op->type_c));
|
||||
else
|
||||
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c));
|
||||
Sys_Printf ("%s", PR_GlobalStringNoContents (pr, s->c,
|
||||
op->type_c));
|
||||
}
|
||||
}
|
||||
Sys_Printf ("\n");
|
||||
|
@ -598,6 +600,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
OPC.integer_var = pointer;
|
||||
break;
|
||||
|
||||
case OP_LEAI:
|
||||
pointer = OPA.integer_var + (short) st->b;
|
||||
OPC.integer_var = pointer;
|
||||
break;
|
||||
|
||||
case OP_STOREB_F:
|
||||
case OP_STOREB_S:
|
||||
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.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.v", OP_STORE_V, true, ev_vector, ev_vector, ev_void, PROG_ID_VERSION},
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#! /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_temp, // temporary variable
|
||||
ex_nil, // umm, nil, null. nuff said
|
||||
ex_name,
|
||||
|
||||
ex_string,
|
||||
ex_float,
|
||||
|
|
|
@ -283,10 +283,13 @@ typedef struct type_s
|
|||
etype_t type;
|
||||
struct def_s *def; // a def that points to this type
|
||||
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
|
||||
int num_parms; // -1 = variable args
|
||||
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;
|
||||
|
||||
typedef struct statref_s {
|
||||
|
@ -359,6 +362,7 @@ extern type_t type_quaternion;
|
|||
extern type_t type_integer;
|
||||
extern type_t type_uinteger;
|
||||
extern type_t type_short;
|
||||
extern type_t type_struct;
|
||||
|
||||
extern def_t def_void;
|
||||
extern def_t def_string;
|
||||
|
@ -372,6 +376,7 @@ extern def_t def_quaternion;
|
|||
extern def_t def_integer;
|
||||
extern def_t def_uinteger;
|
||||
extern def_t def_short;
|
||||
extern def_t def_struct;
|
||||
|
||||
struct function_s
|
||||
{
|
||||
|
|
|
@ -33,5 +33,5 @@ YFLAGS = -d
|
|||
|
||||
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
|
||||
|
|
|
@ -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) {
|
||||
var_c = NULL;
|
||||
statement->c = 0;
|
||||
} else {
|
||||
statement->c = var_c->ofs;
|
||||
}
|
||||
ret = var_a;
|
||||
} else { // allocate result space
|
||||
|
@ -249,6 +251,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
emit_expr (e);
|
||||
break;
|
||||
}
|
||||
case ex_name:
|
||||
case ex_nil:
|
||||
case ex_label:
|
||||
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->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 {
|
||||
abort ();
|
||||
}
|
||||
|
@ -335,6 +356,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
d = PR_NewDef (&type_short, 0, pr_scope);
|
||||
d->ofs = e->e.short_val;
|
||||
d->absolute = 1;
|
||||
d->users = 1;
|
||||
break;
|
||||
}
|
||||
PR_FreeTempDefs ();
|
||||
|
@ -454,6 +476,7 @@ emit_expr (expr_t *e)
|
|||
warning (e, "Ignoring useless expression");
|
||||
break;
|
||||
case ex_nil:
|
||||
case ex_name:
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ static const char rcsid[] =
|
|||
|
||||
#include "qfcc.h"
|
||||
#include "scope.h"
|
||||
#include "struct.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
|
||||
|
@ -51,6 +52,7 @@ etype_t qc_types[] = {
|
|||
ev_void, // ex_def
|
||||
ev_void, // ex_temp
|
||||
ev_void, // ex_nil
|
||||
ev_void, // ex_name
|
||||
|
||||
ev_string, // ex_string
|
||||
ev_float, // ex_float
|
||||
|
@ -93,13 +95,31 @@ expr_type expr_types[] = {
|
|||
ex_integer, // ev_integer
|
||||
ex_uinteger, // ev_uinteger
|
||||
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 *
|
||||
get_type (expr_t *e)
|
||||
{
|
||||
convert_name (e);
|
||||
switch (e->type) {
|
||||
case ex_label:
|
||||
case ex_name:
|
||||
return 0; // something went very wrong
|
||||
case ex_nil:
|
||||
return &type_void;
|
||||
|
@ -487,6 +507,7 @@ print_expr (expr_t *e)
|
|||
printf ("NULL");
|
||||
break;
|
||||
case ex_string:
|
||||
case ex_name:
|
||||
printf ("\"%s\"", e->e.string_val);
|
||||
break;
|
||||
case ex_float:
|
||||
|
@ -798,8 +819,36 @@ field_expr (expr_t *e1, expr_t *e2)
|
|||
{
|
||||
etype_t t1, t2;
|
||||
expr_t *e;
|
||||
type_t *strct;
|
||||
struct_field_t *field;
|
||||
|
||||
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);
|
||||
|
||||
if ((t1 != ev_entity || t2 != ev_field)
|
||||
|
@ -831,8 +880,7 @@ test_expr (expr_t *e, int test)
|
|||
error (e, "internal error");
|
||||
abort ();
|
||||
case ev_void:
|
||||
error (e, "void has no value");
|
||||
break;
|
||||
return error (e, "void has no value");
|
||||
case ev_string:
|
||||
new = new_expr ();
|
||||
new->type = ex_string;
|
||||
|
@ -871,6 +919,8 @@ test_expr (expr_t *e, int test)
|
|||
new = new_expr ();
|
||||
new->type = ex_quaternion;
|
||||
break;
|
||||
case ev_struct:
|
||||
return error (e, "struct cannot be tested");
|
||||
}
|
||||
new->line = e->line;
|
||||
new->file = e->file;
|
||||
|
@ -894,9 +944,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
type_t *type = 0;
|
||||
expr_t *e;
|
||||
|
||||
convert_name (e1);
|
||||
if (op != '=')
|
||||
check_initialized (e1);
|
||||
check_initialized (e2);
|
||||
|
||||
if (op == '=' && e1->type == ex_def)
|
||||
PR_DefInitialized (e1->e.def);
|
||||
|
@ -911,6 +961,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
if (op == '.')
|
||||
return field_expr (e1, e2);
|
||||
|
||||
convert_name (e2);
|
||||
check_initialized (e2);
|
||||
|
||||
if (op == OR || op == AND) {
|
||||
e1 = test_expr (e1, true);
|
||||
e2 = test_expr (e2, true);
|
||||
|
@ -1028,11 +1081,13 @@ asx_expr (int op, expr_t *e1, expr_t *e2)
|
|||
expr_t *
|
||||
unary_expr (int op, expr_t *e)
|
||||
{
|
||||
convert_name (e);
|
||||
check_initialized (e);
|
||||
switch (op) {
|
||||
case '-':
|
||||
switch (e->type) {
|
||||
case ex_label:
|
||||
case ex_name:
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
case ex_uexpr:
|
||||
|
@ -1084,6 +1139,8 @@ unary_expr (int op, expr_t *e)
|
|||
case '!':
|
||||
switch (e->type) {
|
||||
case ex_label:
|
||||
case ex_name:
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
case ex_block:
|
||||
if (!e->e.block.result)
|
||||
|
@ -1142,13 +1199,15 @@ unary_expr (int op, expr_t *e)
|
|||
case '~':
|
||||
switch (e->type) {
|
||||
case ex_label:
|
||||
case ex_name:
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '~')
|
||||
return e->e.expr.e1;
|
||||
case ex_block:
|
||||
if (!e->e.block.result)
|
||||
return error (e, "invalid type for unary -");
|
||||
return error (e, "invalid type for unary ~");
|
||||
case ex_expr:
|
||||
case ex_def:
|
||||
case ex_temp:
|
||||
|
@ -1183,8 +1242,54 @@ unary_expr (int op, expr_t *e)
|
|||
return error (e, "invalid type for unary ~");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
case '&':
|
||||
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");
|
||||
abort ();
|
||||
|
|
|
@ -102,6 +102,14 @@ PR_GetArray (type_t *etype, const char *name, int size, def_t *scope,
|
|||
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
|
||||
|
||||
|
@ -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);
|
||||
char element[MAX_NAME];
|
||||
int size;
|
||||
|
||||
if (def || !allocate)
|
||||
return def;
|
||||
|
@ -147,7 +156,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
|||
d->used = 1;
|
||||
d->parent = def;
|
||||
} else {
|
||||
*allocate += pr_type_size[type->type];
|
||||
*allocate += PR_GetTypeSize(type);
|
||||
}
|
||||
|
||||
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->parent = def;
|
||||
} else if (type->aux_type->type == ev_pointer) {
|
||||
pr.size_fields += type->aux_type->num_parms
|
||||
* pr_type_size[type->aux_type->aux_type->type];
|
||||
size = PR_GetTypeSize (type->aux_type->aux_type);
|
||||
pr.size_fields += type->aux_type->num_parms * size;
|
||||
} 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) {
|
||||
*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;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ type_t type_quaternion = { ev_quaternion, &def_quaternion };
|
|||
type_t type_integer = { ev_integer, &def_integer };
|
||||
type_t type_uinteger = { ev_uinteger, &def_uinteger };
|
||||
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 };
|
||||
|
||||
|
@ -83,6 +84,7 @@ def_t def_quaternion = { &type_quaternion, "temp" };
|
|||
def_t def_integer = { &type_integer, "temp" };
|
||||
def_t def_uinteger = { &type_uinteger, "temp" };
|
||||
def_t def_short = { &type_short, "temp" };
|
||||
def_t def_struct = { &type_struct, "temp" };
|
||||
|
||||
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
|
||||
def = malloc (sizeof (def_t));
|
||||
|
||||
if (!check)
|
||||
if (!def)
|
||||
Sys_Error ("PR_FindType: Memory Allocation Failure\n");
|
||||
def->name = "COMPLEX TYPE";
|
||||
def->type = check;
|
||||
|
|
|
@ -35,6 +35,7 @@ static const char rcsid[] =
|
|||
#include <QF/sys.h>
|
||||
#include "qfcc.h"
|
||||
#include "scope.h"
|
||||
#include "struct.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
#define YY_NO_UNPUT
|
||||
|
@ -227,6 +228,7 @@ static keyword_t keywords[] = {
|
|||
{"case", CASE, 0, PROG_ID_VERSION},
|
||||
{"default", DEFAULT, 0, PROG_ID_VERSION},
|
||||
{"NIL", NIL, 0, PROG_ID_VERSION},
|
||||
{"struct", STRUCT, 0, PROG_VERSION},
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
@ -238,23 +240,27 @@ keyword_get_key (void *kw, void *unused)
|
|||
int
|
||||
type_or_name (char *token)
|
||||
{
|
||||
static int initialized = 0;
|
||||
static hashtab_t *keyword_tab;
|
||||
keyword_t *keyword;
|
||||
keyword_t *keyword;
|
||||
type_t *type;
|
||||
|
||||
if (!initialized) {
|
||||
if (!keyword_tab) {
|
||||
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.code.progsversion)
|
||||
Hash_Add (keyword_tab, &keywords[i]);
|
||||
initialized = 1;
|
||||
}
|
||||
keyword = Hash_Find (keyword_tab, token);
|
||||
if (keyword) {
|
||||
yylval.type = keyword->type;
|
||||
return keyword->value;
|
||||
}
|
||||
type = find_struct (token);
|
||||
if (type) {
|
||||
yylval.type = type;
|
||||
return TYPE;
|
||||
}
|
||||
yylval.string_val = strdup (token);
|
||||
return NAME;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ static const char rcsid[] =
|
|||
#include <QF/hash.h>
|
||||
#include <QF/sys.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "switch.h"
|
||||
|
||||
#define YYDEBUG 1
|
||||
|
@ -110,7 +111,7 @@ typedef struct {
|
|||
|
||||
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
|
||||
%token IFBE IFB IFAE IFA
|
||||
%token SWITCH CASE DEFAULT
|
||||
%token SWITCH CASE DEFAULT STRUCT
|
||||
%token <type> TYPE
|
||||
|
||||
%type <type> type opt_func func_parms array_decl
|
||||
|
@ -137,6 +138,7 @@ expr_t *local_expr;
|
|||
expr_t *break_label;
|
||||
expr_t *continue_label;
|
||||
switch_block_t *switch_block;
|
||||
type_t *struct_type;
|
||||
|
||||
def_t *pr_scope; // the function being parsed, or NULL
|
||||
string_t s_file; // filename for function definition
|
||||
|
@ -157,6 +159,22 @@ def
|
|||
{ current_type = build_type ($1, $4); } var_def_list
|
||||
| opt_field TYPE { current_type = $2; } func_parms
|
||||
{ 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
|
||||
|
@ -218,6 +236,15 @@ array_decl
|
|||
| '[' ']' { $$ = 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_item
|
||||
| var_def_item
|
||||
|
@ -683,12 +710,8 @@ expr
|
|||
| NAME
|
||||
{
|
||||
$$ = new_expr ();
|
||||
$$->type = ex_def;
|
||||
$$->e.def = PR_GetDef (NULL, $1, pr_scope, false);
|
||||
if (!$$->e.def) {
|
||||
error (0, "Undeclared variable \"%s\".", $1);
|
||||
$$->e.def = &def_float;
|
||||
}
|
||||
$$->type = ex_name;
|
||||
$$->e.string_val = $1;
|
||||
}
|
||||
| const { $$ = $1; }
|
||||
| '(' expr ')' { $$ = $2; $$->paren = 1; }
|
||||
|
@ -805,6 +828,14 @@ build_type (int is_field, type_t *type)
|
|||
new.type = ev_field;
|
||||
new.aux_type = type;
|
||||
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 {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ new_struct_field (type_t *strct, type_t *type, const char *name)
|
|||
field->next = 0;
|
||||
*strct->struct_tail = field;
|
||||
strct->struct_tail = &field->next;
|
||||
return 0;
|
||||
Hash_Add (strct->struct_fields, field);
|
||||
return field;
|
||||
}
|
||||
|
||||
struct_field_t *
|
||||
|
|
Loading…
Reference in a new issue