mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
enum support
This commit is contained in:
parent
d5fb0f5a68
commit
64c5983742
7 changed files with 137 additions and 15 deletions
|
@ -128,6 +128,7 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
|||
expr_t *new_unary_expr (int op, expr_t *e1);
|
||||
expr_t *new_temp_def_expr (type_t *type);
|
||||
expr_t *new_bind_expr (expr_t *e1, expr_t *e2);
|
||||
expr_t *new_name_expr (const char *name);
|
||||
|
||||
void inc_users (expr_t *e);
|
||||
|
||||
|
|
|
@ -45,4 +45,7 @@ struct_field_t *struct_find_field (struct type_s *strct, const char *name);
|
|||
struct type_s *new_struct (const char *name);
|
||||
struct type_s *find_struct (const char *name);
|
||||
|
||||
void process_enum (struct expr_s *enm);
|
||||
expr_t *get_enum (const char *name);
|
||||
|
||||
#endif//__struct_h
|
||||
|
|
|
@ -103,14 +103,22 @@ void
|
|||
convert_name (expr_t *e)
|
||||
{
|
||||
if (e->type == ex_name) {
|
||||
const char * name = e->e.string_val;
|
||||
const char *name = e->e.string_val;
|
||||
def_t *d = PR_GetDef (NULL, name, pr_scope, 0);
|
||||
expr_t *enm;
|
||||
|
||||
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;
|
||||
if (d) {
|
||||
e->type = ex_def;
|
||||
e->e.def = d;
|
||||
return;
|
||||
}
|
||||
enm = get_enum (name);
|
||||
if (enm) {
|
||||
e->type = ex_integer;
|
||||
e->e.integer_val = enm->e.integer_val;
|
||||
return;
|
||||
}
|
||||
error (e, "Undeclared variable \"%s\".", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,6 +426,15 @@ new_bind_expr (expr_t *e1, expr_t *e2)
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_name_expr (const char *name)
|
||||
{
|
||||
expr_t *e = new_expr ();
|
||||
e->type = ex_name;
|
||||
e->e.string_val = name;
|
||||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
append_expr (expr_t *block, expr_t *e)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@ static const char rcsid[] =
|
|||
#include <QF/sys.h>
|
||||
|
||||
#include "qfcc.h"
|
||||
#include "struct.h"
|
||||
|
||||
typedef struct locref_s {
|
||||
struct locref_s *next;
|
||||
|
@ -60,6 +61,10 @@ 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 (!scope && (find_struct (name) || get_enum (name))) {
|
||||
error (0, "%s redeclared", name);
|
||||
return 0;
|
||||
}
|
||||
// see if the name is already in use
|
||||
def = (def_t *) Hash_Find (defs_by_name, name);
|
||||
if (def) {
|
||||
|
|
|
@ -241,6 +241,7 @@ static keyword_t keywords[] = {
|
|||
{"default", DEFAULT, 0, PROG_ID_VERSION},
|
||||
{"NIL", NIL, 0, PROG_ID_VERSION},
|
||||
{"struct", STRUCT, 0, PROG_VERSION},
|
||||
{"enum", ENUM, 0, PROG_ID_VERSION},
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
|
|
@ -110,7 +110,7 @@ typedef struct {
|
|||
|
||||
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
|
||||
%token IFBE IFB IFAE IFA
|
||||
%token SWITCH CASE DEFAULT STRUCT
|
||||
%token SWITCH CASE DEFAULT STRUCT ENUM
|
||||
%token <type> TYPE
|
||||
|
||||
%type <type> type opt_func func_parms array_decl
|
||||
|
@ -120,7 +120,7 @@ typedef struct {
|
|||
%type <def> func_def_item func_def_list
|
||||
%type <expr> const opt_expr expr arg_list element_list element_list1 element
|
||||
%type <expr> statement statements statement_block
|
||||
%type <expr> break_label continue_label
|
||||
%type <expr> break_label continue_label enum_list enum
|
||||
%type <function> begin_function
|
||||
%type <def_list> save_inits
|
||||
%type <switch_block> switch_block
|
||||
|
@ -160,6 +160,8 @@ def
|
|||
{ current_type = build_type ($1, $4); } func_def_list
|
||||
| STRUCT NAME
|
||||
{ struct_type = new_struct ($2); } '=' '{' struct_defs '}'
|
||||
| ENUM '{' enum_list opt_comma '}'
|
||||
{ process_enum ($3); }
|
||||
;
|
||||
|
||||
struct_defs
|
||||
|
@ -176,6 +178,34 @@ struct_def
|
|||
{ current_type = build_type ($1, $4); } struct_def_list
|
||||
;
|
||||
|
||||
enum_list
|
||||
: enum
|
||||
| enum_list ',' enum
|
||||
{
|
||||
if ($3) {
|
||||
$3->next = $1;
|
||||
$$ = $3;
|
||||
} else {
|
||||
$$ = $1;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
enum
|
||||
: NAME { $$ = new_name_expr ($1); }
|
||||
| NAME '=' expr
|
||||
{
|
||||
$$ = 0;
|
||||
if ($3->type < ex_string) {
|
||||
error ($3, "non-constant initializer");
|
||||
} else if ($3->type != ex_integer) {
|
||||
error ($3, "invalid initializer type");
|
||||
} else {
|
||||
$$ = new_binary_expr ('=', new_name_expr ($1), $3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
opt_field
|
||||
: /* empty */ { $$ = 0; }
|
||||
| '.' { $$ = 1; }
|
||||
|
@ -251,7 +281,7 @@ var_def_item
|
|||
: def_name opt_var_initializer
|
||||
{
|
||||
$$ = $1;
|
||||
if (!$$->scope && $$->type->type != ev_func)
|
||||
if ($$ && !$$->scope && $$->type->type != ev_func)
|
||||
PR_DefInitialized ($$);
|
||||
}
|
||||
;
|
||||
|
@ -758,12 +788,7 @@ expr
|
|||
| '&' expr %prec UNARY { $$ = address_expr ($2, 0, 0); }
|
||||
| INCOP expr { $$ = incop_expr ($1, $2, 0); }
|
||||
| expr INCOP { $$ = incop_expr ($2, $1, 1); }
|
||||
| NAME
|
||||
{
|
||||
$$ = new_expr ();
|
||||
$$->type = ex_name;
|
||||
$$->e.string_val = $1;
|
||||
}
|
||||
| NAME { $$ = new_name_expr ($1); }
|
||||
| const { $$ = $1; }
|
||||
| '(' expr ')' { $$ = $2; $$->paren = 1; }
|
||||
;
|
||||
|
|
|
@ -31,6 +31,7 @@ static const char rcsid[] =
|
|||
"$Id$";
|
||||
|
||||
#include <QF/hash.h>
|
||||
#include <QF/sys.h>
|
||||
|
||||
#include "qfcc.h"
|
||||
#include "struct.h"
|
||||
|
@ -40,7 +41,13 @@ typedef struct {
|
|||
type_t *type;
|
||||
} struct_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
expr_t value;
|
||||
} enum_t;
|
||||
|
||||
static hashtab_t *structs;
|
||||
static hashtab_t *enums;
|
||||
|
||||
static const char *
|
||||
structs_get_key (void *s, void *unused)
|
||||
|
@ -54,6 +61,12 @@ struct_field_get_key (void *f, void *unused)
|
|||
return ((struct_field_t *) f)->name;
|
||||
}
|
||||
|
||||
static const char *
|
||||
enums_get_key (void *e, void *unused)
|
||||
{
|
||||
return ((enum_t *) e)->name;
|
||||
}
|
||||
|
||||
struct_field_t *
|
||||
new_struct_field (type_t *strct, type_t *type, const char *name)
|
||||
{
|
||||
|
@ -116,3 +129,60 @@ find_struct (const char *name)
|
|||
return strct->type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
process_enum (expr_t *enm)
|
||||
{
|
||||
expr_t *e = enm;
|
||||
expr_t *c_enum = 0;
|
||||
int enum_val = 0;
|
||||
|
||||
if (!enums) {
|
||||
enums = Hash_NewTable (16381, enums_get_key, 0, 0);
|
||||
}
|
||||
while (e) {
|
||||
expr_t *t = e->next;
|
||||
e->next = c_enum;
|
||||
c_enum = e;
|
||||
e = t;
|
||||
}
|
||||
for (e = c_enum; e; e = e->next) {
|
||||
expr_t *name = e;
|
||||
expr_t *val = 0;
|
||||
enum_t *new_enum;
|
||||
|
||||
if (name->type == ex_expr) {
|
||||
val = name->e.expr.e2;
|
||||
name = name->e.expr.e1;
|
||||
}
|
||||
if ((structs && find_struct (name->e.string_val))
|
||||
|| get_enum (name->e.string_val)
|
||||
|| PR_GetDef (NULL, name->e.string_val, 0, 0)) {
|
||||
error (name, "%s redeclared", name->e.string_val);
|
||||
continue;
|
||||
}
|
||||
if (val)
|
||||
enum_val = val->e.integer_val;
|
||||
new_enum = malloc (sizeof (enum_t));
|
||||
if (!new_enum)
|
||||
Sys_Error ("out of memory");
|
||||
new_enum->name = name->e.string_val;
|
||||
new_enum->value.type = ex_integer;
|
||||
new_enum->value.e.integer_val = enum_val++;
|
||||
Hash_Add (enums, new_enum);
|
||||
//printf ("%s = %d\n", new_enum->name, new_enum->value.e.integer_val);
|
||||
}
|
||||
}
|
||||
|
||||
expr_t *
|
||||
get_enum (const char *name)
|
||||
{
|
||||
enum_t *e;
|
||||
|
||||
if (!enums)
|
||||
return 0;
|
||||
e = (enum_t *) Hash_Find (enums, name);
|
||||
if (!e)
|
||||
return 0;
|
||||
return &e->value;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue