enums
authorMichael Wallner <mike@php.net>
Wed, 27 Jan 2016 17:17:10 +0000 (18:17 +0100)
committerMichael Wallner <mike@php.net>
Wed, 27 Jan 2016 17:17:10 +0000 (18:17 +0100)
Makefile.frag
config.m4
src/calc.c
src/context.c
src/context_dump.c
src/context_validate.c
src/module.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y

index 1917557..38fe137 100644 (file)
@@ -25,7 +25,7 @@ lemon.c:
 ./lemon: lemon.c | lempar.c
        $(CC) -o $@ $<
 
 ./lemon: lemon.c | lempar.c
        $(CC) -o $@ $<
 
-$(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.y
+$(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.c
 
 $(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
        touch $@
 
 $(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
        touch $@
index 16db302..ade6f45 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -105,10 +105,11 @@ if test "$PHP_PSI" != no; then
        PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src)
 
        PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && echo *.h)`
        PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src)
 
        PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && echo *.h)`
-       PHP_PSI_SOURCES=`(cd $PHP_PSI_SRCDIR && echo src/context*.c)`
+       PHP_PSI_SOURCES= # parser* should come first
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/parser_proc.c src/parser.c"
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/libjit.c src/libffi.c src/engine.c"
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/marshal.c src/calc.c src/module.c"
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/parser_proc.c src/parser.c"
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/libjit.c src/libffi.c src/engine.c"
        PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/marshal.c src/calc.c src/module.c"
+       PHP_PSI_SOURCES="$PHP_PSI_SOURCES `(cd $PHP_PSI_SRCDIR && echo src/context*.c)`"
 
        PHP_NEW_EXTENSION(psi, $PHP_PSI_SOURCES, $ext_shared)
        PHP_INSTALL_HEADERS(ext/psi, php_psi.h $PHP_PSI_HEADERS)
 
        PHP_NEW_EXTENSION(psi, $PHP_PSI_SOURCES, $ext_shared)
        PHP_INSTALL_HEADERS(ext/psi, php_psi.h $PHP_PSI_HEADERS)
index fc3e043..efea900 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "php.h"
 #include "php_psi.h"
 
 #include "php.h"
 #include "php_psi.h"
+#include "calc.h"
 
 static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) {
        impl_val *ref, *tmp = NULL;
 
 static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) {
        impl_val *ref, *tmp = NULL;
@@ -31,6 +32,10 @@ static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val
                }
                break;
 
                }
                break;
 
+       case PSI_T_ENUM:
+               return psi_calc_num_exp(exp->u.enm->num ?: &exp->u.enm->inc, NULL, res);
+               break;
+
        case PSI_T_NAME:
                if (strct) {
                        ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
        case PSI_T_NAME:
                if (strct) {
                        ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
index de72810..3fe6c3f 100644 (file)
@@ -26,7 +26,7 @@
 #include "php.h"
 #include "php_scandir.h"
 #include "php_psi.h"
 #include "php.h"
 #include "php_scandir.h"
 #include "php_psi.h"
-
+#include "calc.h"
 #include "libjit.h"
 #include "libffi.h"
 
 #include "libjit.h"
 #include "libffi.h"
 
@@ -220,13 +220,12 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths)
 zend_function_entry *PSI_ContextCompile(PSI_Context *C)
 {
        size_t i;
 zend_function_entry *PSI_ContextCompile(PSI_Context *C)
 {
        size_t i;
+       zend_constant zc;
 
 
-       if (C->consts) {
-               zend_constant zc;
-
-               zc.flags = CONST_PERSISTENT|CONST_CS;
-               zc.module_number = EG(current_module)->module_number;
+       zc.flags = CONST_PERSISTENT|CONST_CS;
+       zc.module_number = EG(current_module)->module_number;
 
 
+       if (C->consts) {
                for (i = 0; i < C->consts->count; ++i) {
                        constant *c = C->consts->list[i];
 
                for (i = 0; i < C->consts->count; ++i) {
                        constant *c = C->consts->list[i];
 
@@ -247,6 +246,22 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C)
                        zend_register_constant(&zc);
                }
        }
                        zend_register_constant(&zc);
                }
        }
+       if (C->enums) {
+               for (i = 0; i < C->enums->count; ++i) {
+                       decl_enum *e = C->enums->list[i];
+                       size_t j;
+
+                       for (j = 0; j < e->items->count; ++j) {
+                               decl_enum_item *i = e->items->list[j];
+                               zend_string *name = strpprintf(0, "psi\\%s\\%s", e->name, i->name);
+
+                               zc.name = zend_string_dup(name, 1);
+                               ZVAL_LONG(&zc.value, psi_long_num_exp(i->num, NULL));
+                               zend_register_constant(&zc);
+                               zend_string_release(name);
+                       }
+               }
+       }
 
        return C->closures = C->ops->compile(C);
 }
 
        return C->closures = C->ops->compile(C);
 }
@@ -301,6 +316,12 @@ void PSI_ContextDtor(PSI_Context *C)
                }
                free(C->structs);
        }
                }
                free(C->structs);
        }
+       if (C->enums) {
+               if (C->enums->list) {
+                       free(C->enums->list);
+               }
+               free(C->enums);
+       }
        if (C->decls) {
                if (C->decls->list) {
                        free(C->decls->list);
        if (C->decls) {
                if (C->decls->list) {
                        free(C->decls->list);
index 93b8f32..cb1825f 100644 (file)
@@ -46,6 +46,9 @@ static inline void dump_num_exp(int fd, num_exp *exp) {
                case PSI_T_NAME:
                        dump_decl_var(fd, exp->u.dvar);
                        break;
                case PSI_T_NAME:
                        dump_decl_var(fd, exp->u.dvar);
                        break;
+               case PSI_T_ENUM:
+                       dprintf(fd, "%s", exp->u.enm->name);
+                       break;
                EMPTY_SWITCH_DEFAULT_CASE();
                }
                if (exp->operand) {
                EMPTY_SWITCH_DEFAULT_CASE();
                }
                if (exp->operand) {
@@ -144,6 +147,7 @@ static inline void dump_struct(int fd, decl_struct *strct) {
                dprintf(fd, ";");
        }
 }
                dprintf(fd, ";");
        }
 }
+
 static inline void dump_structs(int fd, decl_structs *structs) {
        size_t i;
 
 static inline void dump_structs(int fd, decl_structs *structs) {
        size_t i;
 
@@ -155,6 +159,35 @@ static inline void dump_structs(int fd, decl_structs *structs) {
        }
 }
 
        }
 }
 
+static inline void dump_enum(int fd, decl_enum *e) {
+       size_t j;
+
+       dprintf(fd, "enum %s {\n", e->name);
+       for (j = 0; j < e->items->count; ++j) {
+               decl_enum_item *i = e->items->list[j];
+
+               if (j) {
+                       dprintf(fd, ",\n");
+               }
+               dprintf(fd, "\t%s", i->name);
+               if (i->num && i->num != &i->inc) {
+                       dprintf(fd, " = ");
+                       dump_num_exp(fd, i->num);
+               }
+       }
+       dprintf(fd, "\n}");
+}
+
+static inline void dump_enums(int fd, decl_enums *enums) {
+       size_t i;
+
+       for (i = 0; i < enums->count; ++i) {
+               decl_enum *e = enums->list[i];
+
+               dump_enum(fd, e);
+               dprintf(fd, "\n");
+       }
+}
 static inline void dump_constant(int fd, constant *cnst) {
        dprintf(fd, "const %s %s = ", cnst->type->name, cnst->name);
        if (cnst->val->type == PSI_T_QUOTED_STRING) {
 static inline void dump_constant(int fd, constant *cnst) {
        dprintf(fd, "const %s %s = ", cnst->type->name, cnst->name);
        if (cnst->val->type == PSI_T_QUOTED_STRING) {
@@ -376,6 +409,10 @@ void PSI_ContextDump(PSI_Context *C, int fd)
                dump_structs(fd, C->structs);
                dprintf(fd, "\n");
        }
                dump_structs(fd, C->structs);
                dprintf(fd, "\n");
        }
+       if (C->enums) {
+               dump_enums(fd, C->enums);
+               dprintf(fd, "\n");
+       }
        if (C->consts) {
                dump_constants(fd, C->consts);
                dprintf(fd, "\n");
        if (C->consts) {
                dump_constants(fd, C->consts);
                dprintf(fd, "\n");
index 38e0f84..66b2a77 100644 (file)
@@ -1,4 +1,4 @@
-#ifdef HAVE_CONFIG_H
+       #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
 # include "config.h"
 #endif
 
@@ -65,6 +65,7 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
 
        return 0;
 }
 
        return 0;
 }
+
 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
        size_t i;
 
 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
        size_t i;
 
@@ -80,6 +81,21 @@ static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type
        return 0;
 }
 
        return 0;
 }
 
+static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
+       size_t i;
+
+       if (type->enm) {
+               return 1;
+       }
+       for (i = 0; i < enums->count; ++i) {
+               if (!strcmp(enums->list[i]->name, type->name)) {
+                       type->enm = enums->list[i];
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
        switch (type->type) {
        case PSI_T_CHAR:
 static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
        switch (type->type) {
        case PSI_T_CHAR:
@@ -99,6 +115,10 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
                        return 0;
                }
                break;
                        return 0;
                }
                break;
+       case PSI_T_ENUM:
+               if (!data->enums || !locate_decl_type_enum(data->enums, type)) {
+                       return 0;
+               }
        }
        return 1;
 }
        }
        return 1;
 }
@@ -300,7 +320,7 @@ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
        size_t i;
 
 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
        size_t i;
 
-       for (i = 0; i < args->count; ++i) {
+       if (args) for (i = 0; i < args->count; ++i) {
                decl_arg *arg = args->args[i];
 
                if (!strcmp(var->name, arg->var->name)) {
                decl_arg *arg = args->args[i];
 
                if (!strcmp(var->name, arg->var->name)) {
@@ -335,7 +355,35 @@ static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts)
 
        return NULL;
 }
 
        return NULL;
 }
-static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *func, num_exp *exp) {
+static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
+       size_t k;
+
+       if (e) for (k = 0; k < e->items->count; ++k) {
+               decl_enum_item *i = e->items->list[k];
+
+               if (!strcmp(i->name, exp->u.dvar->name)) {
+                       free_decl_var(exp->u.dvar);
+                       exp->t = PSI_T_ENUM;
+                       exp->u.enm = i;
+                       return i;
+               }
+       }
+       return NULL;
+}
+static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
+       size_t j;
+
+       if (enums) for (j = 0; j < enums->count; ++j) {
+               decl_enum *e = enums->list[j];
+               decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
+
+               if (i) {
+                       return i;
+               }
+       }
+       return NULL;
+}
+static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
        if (exp->operand) {
                switch (exp->operator) {
                case PSI_T_PLUS:
        if (exp->operand) {
                switch (exp->operator) {
                case PSI_T_PLUS:
@@ -352,16 +400,18 @@ static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *f
                        break;
                EMPTY_SWITCH_DEFAULT_CASE();
                }
                        break;
                EMPTY_SWITCH_DEFAULT_CASE();
                }
-               if (!validate_num_exp(data, dargs, func, exp->operand)) {
+               if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
                        return 0;
                }
        }
        switch (exp->t) {
        case PSI_T_NAME:
                if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
                        return 0;
                }
        }
        switch (exp->t) {
        case PSI_T_NAME:
                if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
-                       data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
-                                       exp->u.dvar->name);
-                       return 0;
+                       if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
+                               data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
+                                               exp->u.dvar->name);
+                               return 0;
+                       }
                }
                return 1;
        case PSI_T_NSNAME:
                }
                return 1;
        case PSI_T_NSNAME:
@@ -372,11 +422,45 @@ static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *f
                }
                return 1;
        case PSI_T_NUMBER:
                }
                return 1;
        case PSI_T_NUMBER:
+       case PSI_T_ENUM:
                return 1;
        default:
                return 0;
        }
 }
                return 1;
        default:
                return 0;
        }
 }
+
+static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
+       size_t j;
+
+       if (!e->items || !e->items->count) {
+               data->error(e->token, PSI_WARNING, "Empty enum '%s'", e->name);
+               return 0;
+       }
+
+       for (j = 0; j < e->items->count; ++j) {
+               decl_enum_item *i = e->items->list[j];
+
+               if (!i->num) {
+                       if (j) {
+                               i->inc.t = PSI_T_NUMBER;
+                               i->inc.u.numb = "1";
+                               i->inc.operator = PSI_T_PLUS;
+                               i->inc.operand = i->prev->num ?: &i->prev->inc;
+                               i->num = &i->inc;
+                       } else {
+                               i->inc.t = PSI_T_NUMBER;
+                               i->inc.u.numb = "0";
+                               i->num = &i->inc;
+                       }
+               }
+               if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
 static inline int validate_set_value_handler(set_value *set) {
        switch (set->func->type) {
        case PSI_T_TO_BOOL:
 static inline int validate_set_value_handler(set_value *set) {
        switch (set->func->type) {
        case PSI_T_TO_BOOL:
@@ -460,7 +544,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg
                }
        }
        if (set->num) {
                }
        }
        if (set->num) {
-               if (!validate_num_exp(data, ref_list, ref, set->num)) {
+               if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
                        return 0;
                }
        }
                        return 0;
                }
        }
@@ -605,15 +689,15 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
                                                        let->var->array_size));
                        break;
                case PSI_LET_NUMEXP:
                                                        let->var->array_size));
                        break;
                case PSI_LET_NUMEXP:
-                       if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.num)) {
+                       if (!validate_num_exp(data, let->val->data.num, impl->decl->args, impl->decl->func, NULL)) {
                                return 0;
                        }
                        break;
                case PSI_LET_CALLOC:
                                return 0;
                        }
                        break;
                case PSI_LET_CALLOC:
-                       if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.alloc->nmemb)) {
+                       if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
                                return 0;
                        }
                                return 0;
                        }
-                       if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.alloc->size)) {
+                       if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
                                return 0;
                        }
                        break;
                                return 0;
                        }
                        break;
@@ -881,6 +965,15 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
                        }
                }
        }
                        }
                }
        }
+       if (D->enums) {
+               size_t i;
+
+               for (i = 0; i < D->enums->count; ++i) {
+                       if (validate_decl_enum(PSI_DATA(C), D->enums->list[i])) {
+                               C->enums = add_decl_enum(C->enums, D->enums->list[i]);
+                       }
+               }
+       }
        if (D->consts) {
                size_t i;
 
        if (D->consts) {
                size_t i;
 
@@ -960,6 +1053,18 @@ int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
                }
        }
 
                }
        }
 
+       if (source->enums) for (i = 0; i < source->enums->count; ++i) {
+               decl_enum *denum = source->enums->list[i];
+
+               if (validate_decl_enum(source, denum)) {
+                       if (dest) {
+                               dest->enums = add_decl_enum(dest->enums, denum);
+                       }
+               } else {
+                       ++errors;
+               }
+       }
+
        if (source->decls) for (i = 0; i < source->decls->count; ++i) {
                decl *decl = source->decls->list[i];
 
        if (source->decls) for (i = 0; i < source->decls->count; ++i) {
                decl *decl = source->decls->list[i];
 
index c3728a7..f71975b 100644 (file)
@@ -50,7 +50,7 @@ void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...)
                fn = zend_get_executed_filename();
                ln = zend_get_executed_lineno();
        } else if (zend_is_compiling()) {
                fn = zend_get_executed_filename();
                ln = zend_get_executed_lineno();
        } else if (zend_is_compiling()) {
-               fn = zend_get_compiled_filename();
+               fn = zend_get_compiled_filename()->val;
                ln = zend_get_compiled_lineno();
        }
 
                ln = zend_get_compiled_lineno();
        }
 
index 5582922..daf99dc 100644 (file)
@@ -17,7 +17,6 @@
 
 typedef int token_t;
 
 
 typedef int token_t;
 
-/* in php_psi.h */
 size_t psi_t_alignment(token_t);
 size_t psi_t_size(token_t);
 
 size_t psi_t_alignment(token_t);
 size_t psi_t_size(token_t);
 
@@ -61,6 +60,7 @@ typedef struct decl_type {
        token_t type;
        struct decl_type *real;
        struct decl_struct *strct;
        token_t type;
        struct decl_type *real;
        struct decl_struct *strct;
+       struct decl_enum *enm;
 } decl_type;
 
 static inline decl_type *init_decl_type(token_t type, const char *name) {
 } decl_type;
 
 static inline decl_type *init_decl_type(token_t type, const char *name) {
@@ -70,40 +70,6 @@ static inline decl_type *init_decl_type(token_t type, const char *name) {
        return t;
 }
 
        return t;
 }
 
-static inline decl_type *init_decl_type_ex(token_t type, int argc, ...) {
-       va_list argv;
-       char *ptr, *arg;
-       unsigned i;
-       size_t len, pos = 0, all = 0;
-       decl_type *t = calloc(1, sizeof(*t));
-
-       va_start(argv, argc);
-       for (i = 0; i < argc; ++i) {
-               arg = va_arg(argv, char *);
-               len = va_arg(argv, size_t);
-
-               if (len) {
-                       if (all) {
-                               pos = all;
-                               ptr = realloc(ptr, 1 + (all += len));
-                       } else {
-                               ptr = malloc(1 + (all = len));
-                       }
-                       memcpy(ptr + pos, arg, len);
-               }
-       }
-       va_end(argv);
-
-       if (!all) {
-               ptr = calloc(1, 1);
-       } else {
-               ptr[all] = 0;
-       }
-       t->type = type;
-       t->name = ptr;
-       return t;
-}
-
 static inline decl_type *real_decl_type(decl_type *type) {
        while (type->real) {
                type = type->real;
 static inline decl_type *real_decl_type(decl_type *type) {
        while (type->real) {
                type = type->real;
@@ -375,6 +341,7 @@ static inline void free_decls(decls *decls) {
        free(decls);
 }
 
        free(decls);
 }
 
+
 typedef struct decl_struct {
        PSI_Token *token;
        char *name;
 typedef struct decl_struct {
        PSI_Token *token;
        char *name;
@@ -651,6 +618,7 @@ typedef struct num_exp {
                char *numb;
                constant *cnst;
                decl_var *dvar;
                char *numb;
                constant *cnst;
                decl_var *dvar;
+               struct decl_enum_item *enm;
        } u;
        token_t operator;
        int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
        } u;
        token_t operator;
        int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
@@ -672,6 +640,36 @@ static inline num_exp *init_num_exp(token_t t, void *num) {
        return exp;
 }
 
        return exp;
 }
 
+static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
+static inline num_exp *copy_num_exp(num_exp *exp) {
+       decl_var *dvar;
+       num_exp *num = calloc(1, sizeof(*num));
+
+       memcpy(num, exp, sizeof(*num));
+
+       if (num->token) {
+               num->token = PSI_TokenCopy(num->token);
+       }
+       if (num->operand) {
+               num->operand = copy_num_exp(num->operand);
+       }
+       switch (num->t) {
+       case PSI_T_NUMBER:
+       case PSI_T_NSNAME:
+               num->u.numb = strdup(num->u.numb);
+               break;
+       case PSI_T_NAME:
+               dvar = init_decl_var(num->u.dvar->name, num->u.dvar->pointer_level, num->u.dvar->array_size);
+               dvar->arg = num->u.dvar->arg;
+               if (num->u.dvar->token) {
+                       dvar->token = PSI_TokenCopy(num->u.dvar->token);
+               }
+               num->u.dvar = dvar;
+               break;
+       }
+       return num;
+}
+
 static inline void free_num_exp(num_exp *exp) {
        if (exp->token) {
                free(exp->token);
 static inline void free_num_exp(num_exp *exp) {
        if (exp->token) {
                free(exp->token);
@@ -685,6 +683,8 @@ static inline void free_num_exp(num_exp *exp) {
        case PSI_T_NAME:
                free_decl_var(exp->u.dvar);
                break;
        case PSI_T_NAME:
                free_decl_var(exp->u.dvar);
                break;
+       case PSI_T_ENUM:
+               break;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
        if (exp->operand) {
        EMPTY_SWITCH_DEFAULT_CASE();
        }
        if (exp->operand) {
@@ -693,6 +693,122 @@ static inline void free_num_exp(num_exp *exp) {
        free(exp);
 }
 
        free(exp);
 }
 
+typedef struct decl_enum_item {
+       PSI_Token *token;
+       char *name;
+       num_exp *num;
+       num_exp inc;
+       struct decl_enum_item *prev;
+} decl_enum_item;
+
+static inline decl_enum_item *init_decl_enum_item(const char *name, num_exp *num) {
+       decl_enum_item *i = calloc(1, sizeof(*i));
+
+       i->name = strdup(name);
+       i->num = num;
+       return i;
+}
+
+static inline void free_decl_enum_item(decl_enum_item *i) {
+       if (i->token) {
+               free(i->token);
+       }
+       if (i->num && i->num != &i->inc) {
+               free_num_exp(i->num);
+       }
+       free(i->name);
+       free(i);
+}
+
+typedef struct decl_enum_items {
+       decl_enum_item **list;
+       size_t count;
+} decl_enum_items;
+
+static inline decl_enum_items *init_decl_enum_items(decl_enum_item *i) {
+       decl_enum_items *l = calloc(1, sizeof(*l));
+
+       if (i) {
+               l->count = 1;
+               l->list = calloc(1, sizeof(*l->list));
+               l->list[0] = i;
+       }
+       return l;
+}
+
+static inline decl_enum_items *add_decl_enum_item(decl_enum_items *l, decl_enum_item *i) {
+       l->list = realloc(l->list, sizeof(*l->list) * (l->count + 1));
+       l->list[l->count] = i;
+       if (l->count) {
+               i->prev = l->list[l->count - 1];
+       }
+       ++l->count;
+       return l;
+}
+
+static inline void free_decl_enum_items(decl_enum_items *l) {
+       if (l->list) {
+               size_t j;
+
+               for (j = 0; j < l->count; ++j) {
+                       free_decl_enum_item(l->list[j]);
+               }
+               free(l->list);
+       }
+       free(l);
+}
+
+typedef struct decl_enum {
+       PSI_Token *token;
+       char *name;
+       decl_enum_items *items;
+} decl_enum;
+
+static inline decl_enum *init_decl_enum(const char *name, decl_enum_items *l) {
+       decl_enum *e = calloc(1, sizeof(*e));
+
+       e->name = strdup(name);
+       e->items = l;
+       return e;
+}
+
+static inline void free_decl_enum(decl_enum *e) {
+       if (e->token) {
+               free(e->token);
+       }
+       if (e->items) {
+               free_decl_enum_items(e->items);
+       }
+       free(e->name);
+       free(e);
+}
+
+typedef struct decl_enums {
+       decl_enum **list;
+       size_t count;
+} decl_enums;
+
+static inline decl_enums* add_decl_enum(decl_enums *es, decl_enum *e) {
+       if (!es) {
+               es = calloc(1, sizeof(*es));
+       }
+       es->list = realloc(es->list, ++es->count * sizeof(*es->list));
+       es->list[es->count-1] = e;
+       return es;
+}
+
+static inline void free_decl_enums(decl_enums *es) {
+       if (es->list) {
+               size_t j;
+
+               for (j = 0; j < es->count; ++j) {
+                       free_decl_enum(es->list[j]);
+               }
+       }
+       free(es->list);
+       free(es);
+}
+
 typedef struct let_calloc {
        num_exp *nmemb;
        num_exp *size;
 typedef struct let_calloc {
        num_exp *nmemb;
        num_exp *size;
@@ -1250,6 +1366,7 @@ typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...);
        constants *consts; \
        decl_typedefs *defs; \
        decl_structs *structs; \
        constants *consts; \
        decl_typedefs *defs; \
        decl_structs *structs; \
+       decl_enums *enums; \
        decls *decls; \
        impls *impls; \
        union { \
        decls *decls; \
        impls *impls; \
        union { \
@@ -1280,6 +1397,9 @@ static inline void PSI_DataDtor(PSI_Data *data) {
        if (data->structs) {
                free_decl_structs(data->structs);
        }
        if (data->structs) {
                free_decl_structs(data->structs);
        }
+       if (data->enums) {
+               free_decl_enums(data->enums);
+       }
        if (data->decls) {
                free_decls(data->decls);
        }
        if (data->decls) {
                free_decls(data->decls);
        }
index 7ab169e..50d15aa 100644 (file)
@@ -284,6 +284,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                'FUNCTION' {RETURN(PSI_T_FUNCTION);}
                'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
                'STRUCT' {RETURN(PSI_T_STRUCT);}
                'FUNCTION' {RETURN(PSI_T_FUNCTION);}
                'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
                'STRUCT' {RETURN(PSI_T_STRUCT);}
+               'ENUM' {RETURN(PSI_T_ENUM);}
                'CONST' {RETURN(PSI_T_CONST);}
                'LIB' {RETURN(PSI_T_LIB);}
                'LET' {RETURN(PSI_T_LET);}
                'CONST' {RETURN(PSI_T_CONST);}
                'LIB' {RETURN(PSI_T_LIB);}
                'LET' {RETURN(PSI_T_LET);}
index 7e8a7fe..c6fe15a 100644 (file)
 #define PSI_T_EOF                             13
 #define PSI_T_EOS                             14
 #define PSI_T_QUOTED_STRING                   15
 #define PSI_T_EOF                             13
 #define PSI_T_EOS                             14
 #define PSI_T_QUOTED_STRING                   15
-#define PSI_T_STRUCT                          16
+#define PSI_T_ENUM                            16
 #define PSI_T_LBRACE                          17
 #define PSI_T_RBRACE                          18
 #define PSI_T_LBRACE                          17
 #define PSI_T_RBRACE                          18
-#define PSI_T_COLON                           19
-#define PSI_T_LPAREN                          20
-#define PSI_T_NUMBER                          21
-#define PSI_T_RPAREN                          22
-#define PSI_T_BOOL                            23
-#define PSI_T_INT                             24
-#define PSI_T_FLOAT                           25
-#define PSI_T_CONST                           26
-#define PSI_T_NSNAME                          27
-#define PSI_T_EQUALS                          28
-#define PSI_T_TYPEDEF                         29
-#define PSI_T_VOID                            30
-#define PSI_T_LBRACKET                        31
-#define PSI_T_RBRACKET                        32
-#define PSI_T_COMMA                           33
-#define PSI_T_ELLIPSIS                        34
-#define PSI_T_CHAR                            35
-#define PSI_T_SHORT                           36
-#define PSI_T_LONG                            37
-#define PSI_T_DOUBLE                          38
-#define PSI_T_UNSIGNED                        39
-#define PSI_T_SIGNED                          40
-#define PSI_T_INT8                            41
-#define PSI_T_UINT8                           42
-#define PSI_T_INT16                           43
-#define PSI_T_UINT16                          44
-#define PSI_T_INT32                           45
-#define PSI_T_UINT32                          46
-#define PSI_T_INT64                           47
-#define PSI_T_UINT64                          48
-#define PSI_T_FUNCTION                        49
-#define PSI_T_NULL                            50
-#define PSI_T_TRUE                            51
-#define PSI_T_FALSE                           52
-#define PSI_T_DOLLAR                          53
-#define PSI_T_CALLOC                          54
-#define PSI_T_OBJVAL                          55
-#define PSI_T_ARRVAL                          56
-#define PSI_T_PATHVAL                         57
-#define PSI_T_STRLEN                          58
-#define PSI_T_STRVAL                          59
-#define PSI_T_FLOATVAL                        60
-#define PSI_T_INTVAL                          61
-#define PSI_T_BOOLVAL                         62
-#define PSI_T_TO_OBJECT                       63
-#define PSI_T_TO_ARRAY                        64
-#define PSI_T_TO_STRING                       65
-#define PSI_T_TO_INT                          66
-#define PSI_T_TO_FLOAT                        67
-#define PSI_T_TO_BOOL                         68
-#define PSI_T_MIXED                           69
-#define PSI_T_ARRAY                           70
-#define PSI_T_OBJECT                          71
-#define PSI_T_AMPERSAND                       72
+#define PSI_T_COMMA                           19
+#define PSI_T_EQUALS                          20
+#define PSI_T_STRUCT                          21
+#define PSI_T_COLON                           22
+#define PSI_T_LPAREN                          23
+#define PSI_T_NUMBER                          24
+#define PSI_T_RPAREN                          25
+#define PSI_T_BOOL                            26
+#define PSI_T_INT                             27
+#define PSI_T_FLOAT                           28
+#define PSI_T_CONST                           29
+#define PSI_T_NSNAME                          30
+#define PSI_T_TYPEDEF                         31
+#define PSI_T_VOID                            32
+#define PSI_T_LBRACKET                        33
+#define PSI_T_RBRACKET                        34
+#define PSI_T_ELLIPSIS                        35
+#define PSI_T_CHAR                            36
+#define PSI_T_SHORT                           37
+#define PSI_T_LONG                            38
+#define PSI_T_DOUBLE                          39
+#define PSI_T_UNSIGNED                        40
+#define PSI_T_SIGNED                          41
+#define PSI_T_INT8                            42
+#define PSI_T_UINT8                           43
+#define PSI_T_INT16                           44
+#define PSI_T_UINT16                          45
+#define PSI_T_INT32                           46
+#define PSI_T_UINT32                          47
+#define PSI_T_INT64                           48
+#define PSI_T_UINT64                          49
+#define PSI_T_FUNCTION                        50
+#define PSI_T_NULL                            51
+#define PSI_T_TRUE                            52
+#define PSI_T_FALSE                           53
+#define PSI_T_DOLLAR                          54
+#define PSI_T_CALLOC                          55
+#define PSI_T_OBJVAL                          56
+#define PSI_T_ARRVAL                          57
+#define PSI_T_PATHVAL                         58
+#define PSI_T_STRLEN                          59
+#define PSI_T_STRVAL                          60
+#define PSI_T_FLOATVAL                        61
+#define PSI_T_INTVAL                          62
+#define PSI_T_BOOLVAL                         63
+#define PSI_T_TO_OBJECT                       64
+#define PSI_T_TO_ARRAY                        65
+#define PSI_T_TO_STRING                       66
+#define PSI_T_TO_INT                          67
+#define PSI_T_TO_FLOAT                        68
+#define PSI_T_TO_BOOL                         69
+#define PSI_T_MIXED                           70
+#define PSI_T_ARRAY                           71
+#define PSI_T_OBJECT                          72
+#define PSI_T_AMPERSAND                       73
index 1cc466f..328bd10 100644 (file)
@@ -67,6 +67,40 @@ block ::= constant(constant). {
 block ::= decl_struct(strct). {
        P->structs = add_decl_struct(P->structs, strct);
 }
 block ::= decl_struct(strct). {
        P->structs = add_decl_struct(P->structs, strct);
 }
+block ::= decl_enum(e). {
+       P->enums = add_decl_enum(P->enums, e);
+}
+
+enum_name(n) ::= ENUM NAME(N). {
+       n = N;
+}
+
+%type decl_enum {decl_enum *}
+%destructor decl_enum {free_decl_enum($$);}
+decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
+       e = init_decl_enum(N->text, list);
+       e->token = N;
+}
+
+%type decl_enum_items {decl_enum_items*}
+%destructor decl_enum_items {free_decl_enum_items($$);}
+decl_enum_items(l) ::= decl_enum_item(i). {
+       l = init_decl_enum_items(i);
+}
+decl_enum_items(l) ::= decl_enum_items(l_) COMMA decl_enum_item(i). {
+       l = add_decl_enum_item(l_, i);
+}
+
+%type decl_enum_item {decl_enum_item*}
+%destructor decl_enum_item {free_decl_enum_item($$);}
+decl_enum_item(i) ::= NAME(N) EQUALS num_exp(num). {
+       i = init_decl_enum_item(N->text, num);
+       i->token = N;
+}
+decl_enum_item(i) ::= NAME(N). {
+       i = init_decl_enum_item(N->text, NULL);
+       i->token = N;
+}
 
 struct_name(n) ::= STRUCT NAME(N). {
        n = N;
 
 struct_name(n) ::= STRUCT NAME(N). {
        n = N;
@@ -332,6 +366,11 @@ decl_type(type_) ::= STRUCT(S) NAME(T). {
        type_->token = T;
        free(S);
 }
        type_->token = T;
        free(S);
 }
+decl_type(type_) ::= ENUM(E) NAME(T). {
+       type_ = init_decl_type(E->type, T->text);
+       type_->token = T;
+       free(E);
+}
 %token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME.
 %type decl_type {decl_type*}
 %destructor decl_type {free_decl_type($$);}
 %token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME.
 %type decl_type {decl_type*}
 %destructor decl_type {free_decl_type($$);}