flush
authorMichael Wallner <mike@php.net>
Mon, 28 Dec 2015 16:28:38 +0000 (17:28 +0100)
committerMichael Wallner <mike@php.net>
Mon, 28 Dec 2015 16:28:38 +0000 (17:28 +0100)
Makefile.frag
php_psi.h
psi.d/stdio.psi
src/context.c
src/module.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y

index c6ce97d84e1b14d809683dd7d7e8c69ed97e7afd..1917557e9bdcc4f7d09c2a29a25a8bffd068b97b 100644 (file)
@@ -26,7 +26,7 @@ lemon.c:
        $(CC) -o $@ $<
 
 $(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.y
+
 $(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
        touch $@
 $(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser.h
index 367739acc0ef237285d111bd58509c58aa4b797f..f5859e3dacbe155f84a8672e1cc4bcd17f485803 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -18,7 +18,6 @@ extern zend_module_entry psi_module_entry;
 #include "TSRM.h"
 #endif
 
-#include "parser.h"
 #include "context.h"
 
 void psi_error(int type, const char *msg, ...);
index 3e54ac4dd57bcf485909a6d1cf277c99e3a84091..1e136cef1caaa8101152fac63c3bd6134843ba57 100644 (file)
@@ -64,3 +64,9 @@ function psi\rewind(object $stream) : void {
        let stream = objval($stream);
        return void(rewind);
 }
+
+extern int printf(const char *fmt, ...);
+function psi\printf(string $fmt, mixed ...$args) : int {
+       let fmt = strval($fmt);
+       return to_int(printf);
+}
index 5b08426a96bfecf7692b14b0a482508f6b207615..ba9fabb9cc8e0c0d5ed4542e9f92d96cf1a33f1e 100644 (file)
 #include "php.h"
 #include "php_scandir.h"
 #include "php_psi.h"
-#include "context.h"
-#include "parser.h"
 
 #include "libjit.h"
 #include "libffi.h"
@@ -294,8 +292,10 @@ static inline int validate_constant(PSI_Data *data, constant *c) {
 
 static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
        if (!validate_decl_type(data, arg->type)) {
-               data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for '%s'",
-                       arg->type->name, arg->type->type, arg->var->name);
+               data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for decl var '%s'"
+                               " in %s on line %zu at col %zu",
+                       arg->type->name, arg->type->type, arg->var->name,
+                       arg->type->token->file, arg->type->token->line, arg->type->token->col);
                return 0;
        }
        return 1;
@@ -1371,11 +1371,16 @@ void PSI_ContextDump(PSI_Context *C, int fd)
                        dprintf(fd, "%s ", decl->abi->convention);
                        dump_decl_arg(fd, decl->func);
                        dprintf(fd, "(");
-                       if (decl->args) for (j = 0; j < decl->args->count; ++j) {
-                               if (j) {
-                                       dprintf(fd, ", ");
+                       if (decl->args) {
+                               for (j = 0; j < decl->args->count; ++j) {
+                                       if (j) {
+                                               dprintf(fd, ", ");
+                                       }
+                                       dump_decl_arg(fd, decl->args->args[j]);
+                               }
+                               if (decl->args->varargs) {
+                                       dprintf(fd, ", ...");
                                }
-                               dump_decl_arg(fd, decl->args->args[j]);
                        }
                        dprintf(fd, ");\n");
                }
@@ -1386,16 +1391,26 @@ void PSI_ContextDump(PSI_Context *C, int fd)
                        impl *impl = C->impls->list[i];
 
                        dprintf(fd, "function %s(", impl->func->name);
-                       if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
-                               impl_arg *iarg = impl->func->args->args[j];
-
-                               dprintf(fd, "%s%s %s$%s",
-                                               j ? ", " : "",
-                                               iarg->type->name,
-                                               iarg->var->reference ? "&" : "",
-                                               iarg->var->name);
-                               if (iarg->def) {
-                                       dprintf(fd, " = %s", iarg->def->text);
+                       if (impl->func->args) {
+                               for (j = 0; j < impl->func->args->count; ++j) {
+                                       impl_arg *iarg = impl->func->args->args[j];
+
+                                       dprintf(fd, "%s%s %s$%s",
+                                                       j ? ", " : "",
+                                                       iarg->type->name,
+                                                       iarg->var->reference ? "&" : "",
+                                                       iarg->var->name);
+                                       if (iarg->def) {
+                                               dprintf(fd, " = %s", iarg->def->text);
+                                       }
+                               }
+                               if (impl->func->args->vararg) {
+                                       impl_arg *vararg = impl->func->args->vararg;
+
+                                       dprintf(fd, ", %s %s...$%s",
+                                                       vararg->type->name,
+                                                       vararg->var->reference ? "&" : "",
+                                                       vararg->var->name);
                                }
                        }
                        dprintf(fd, ") : %s%s {\n",
index bde40a4524244c2c8bc90d074cfffeeb10186d68..c820f4f1bd0ed47b6b2a873790a78fd3d6f8dbbd 100644 (file)
@@ -11,8 +11,6 @@
 #include "zend_operators.h"
 
 #include "php_psi.h"
-#include "parser.h"
-#include "context.h"
 
 #if HAVE_LIBJIT
 # include "libjit.h"
@@ -124,13 +122,26 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl)
        zend_internal_arg_info *aip;
        zend_internal_function_info *fi;
 
-       aip = calloc(impl->func->args->count + 1, sizeof(*aip));
+       aip = calloc(impl->func->args->count + 1 + !!impl->func->args->vararg, sizeof(*aip));
 
        fi = (zend_internal_function_info *) &aip[0];
+       fi->allow_null = 1;
        fi->required_num_args = psi_num_min_args(impl);
        fi->return_reference = impl->func->return_reference;
        fi->type_hint = psi_internal_type(impl->func->return_type);
 
+       if (impl->func->args->vararg) {
+               impl_arg *vararg = impl->func->args->vararg;
+               zend_internal_arg_info *ai = &aip[impl->func->args->count];
+
+               ai->name = vararg->var->name;
+               ai->type_hint = psi_internal_type(vararg->type);
+               if (vararg->var->reference) {
+                       ai->pass_by_reference = 1;
+               }
+               ai->is_variadic = 1;
+       }
+
        for (i = 0; i < impl->func->args->count; ++i) {
                impl_arg *iarg = impl->func->args->args[i];
                zend_internal_arg_info *ai = &aip[i+1];
@@ -479,7 +490,7 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                return rv;
        }
 
-       ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->count)
+       ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg ? -1 : impl->func->args->count)
        nextarg:
                iarg = impl->func->args->args[_i];
                if (iarg->def) {
@@ -504,6 +515,20 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                        error_code = ZPP_ERROR_FAILURE;
                        break;
                }
+               if (impl->func->args->vararg) {
+                       iarg = impl->func->args->vararg;
+
+                       if (_i == impl->func->args->count) {
+                               zval *ptr = iarg->_zv = calloc(_num_args - _i + 1, sizeof(zval));
+
+                               _optional = 1;
+                               while (_i < _num_args) {
+                                       Z_PARAM_PROLOGUE(0);
+                                       ZVAL_COPY_VALUE(ptr++, _arg);
+                               }
+                               break;
+                       }
+               }
                if (_i < _num_args) {
                        goto nextarg;
                }
index 660b35573f99ce89c8cafd75557c131275fc443d..55f4f9d75f6d57067adacc2e8a43950530cc2dcd 100644 (file)
@@ -21,9 +21,9 @@ size_t psi_t_size(token_t);
 
 typedef struct PSI_Token {
        token_t type;
-       unsigned line;
-       size_t size;
-       char text[1];
+       size_t size, line, col;
+       char *text, *file;
+       char buf[1];
 } PSI_Token;
 
 typedef union impl_val {
@@ -51,6 +51,7 @@ typedef union impl_val {
 } impl_val;
 
 typedef struct decl_type {
+       PSI_Token *token;
        char *name;
        token_t type;
        struct decl_type *real;
@@ -217,6 +218,7 @@ static inline void free_decl_vars(decl_vars *vars) {
 typedef struct decl_args {
        decl_arg **args;
        size_t count;
+       unsigned varargs:1;
 } decl_args;
 
 static inline decl_args *init_decl_args(decl_arg *arg) {
@@ -500,6 +502,7 @@ static inline void free_impl_arg(impl_arg *arg) {
 typedef struct impl_args {
        impl_arg **args;
        size_t count;
+       impl_arg *vararg;
 } impl_args;
 
 static inline impl_args *init_impl_args(impl_arg *arg) {
@@ -1166,38 +1169,58 @@ typedef struct PSI_Parser {
        unsigned flags;
        unsigned errors;
        void *proc;
-       size_t line;
+       size_t line, col;
        token_t num;
        char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
 } PSI_Parser;
 
 static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
        PSI_Token *T;
-       size_t token_len;
+       size_t token_len, fname_len;
+       token_t token_typ;
 
        if (P->cur < P->tok) {
                return NULL;
        }
 
+       token_typ = P->num;
        token_len = P->cur - P->tok;
+       fname_len = strlen(P->psi.file.fn);
 
-       T = calloc(1, sizeof(*T) + token_len);
-       T->type = P->num;
-       T->line = P->line;
+       T = calloc(1, sizeof(*T) + token_len + fname_len + 1);
+       T->type = token_typ;
        T->size = token_len;
-       T->text[token_len] = 0;
+       T->line = P->line;
+       T->col = P->col;
+       T->file = &T->buf[0];
+       T->text = &T->buf[fname_len + 1];
+
+       memcpy(T->file, P->psi.file.fn, fname_len);
        memcpy(T->text, P->tok, token_len);
 
        return T;
 }
 
+static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) {
+       size_t fname_len = strlen(src->file);
+       size_t strct_len = sizeof(*src) + src->size + fname_len + 1;
+       PSI_Token *ptr = malloc(strct_len);
+
+       memcpy(ptr, src, strct_len);
+
+       ptr->file = &ptr->buf[0];
+       ptr->text = &ptr->buf[fname_len + 1];
+
+       return ptr;
+}
+
 #define PSI_PARSER_DEBUG 0x1
 
 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags);
 void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...);
 size_t PSI_ParserFill(PSI_Parser *P, size_t n);
 token_t PSI_ParserScan(PSI_Parser *P);
-void PSI_ParserParse(PSI_Parser *P, PSI_Token *T);
+void PSI_ParserParse(PSI_Parser *P, PSI_Token *src);
 void PSI_ParserDtor(PSI_Parser *P);
 void PSI_ParserFree(PSI_Parser **P);
 
index affe90163e7639b6e81f8dcf9be1aba6f31c4566..69e76c8f124244f9c7920844569dfa5da11c3a80 100644 (file)
@@ -32,6 +32,7 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err
 
        P->psi.file.fn = strdup(filename);
        P->fp = fp;
+       P->col = 1;
        P->line = 1;
        P->error = error;
        P->flags = flags;
@@ -139,17 +140,100 @@ void PSI_ParserFree(PSI_Parser **P)
 # error BSIZE must be greater than YYMAXFILL
 #endif
 
+#define PSI_T(n) \
+(n) == PSI_T_NAME ? "NAME" : \
+(n) == PSI_T_PLUS ? "PLUS" : \
+(n) == PSI_T_MINUS ? "MINUS" : \
+(n) == PSI_T_SLASH ? "SLASH" : \
+(n) == PSI_T_ASTERISK ? "ASTERISK" : \
+(n) == PSI_T_TEMP ? "TEMP" : \
+(n) == PSI_T_FREE ? "FREE" : \
+(n) == PSI_T_SET ? "SET" : \
+(n) == PSI_T_LET ? "LET" : \
+(n) == PSI_T_RETURN ? "RETURN" : \
+(n) == PSI_T_LIB ? "LIB" : \
+(n) == PSI_T_INT ? "INT" : \
+(n) == PSI_T_UNSIGNED ? "UNSIGNED" : \
+(n) == PSI_T_EOF ? "EOF" : \
+(n) == PSI_T_QUOTED_STRING ? "QUOTED_STRING" : \
+(n) == PSI_T_EOS ? "EOS" : \
+(n) == PSI_T_STRUCT ? "STRUCT" : \
+(n) == PSI_T_LBRACE ? "LBRACE" : \
+(n) == PSI_T_RBRACE ? "RBRACE" : \
+(n) == PSI_T_COLON ? "COLON" : \
+(n) == PSI_T_LPAREN ? "LPAREN" : \
+(n) == PSI_T_NUMBER ? "NUMBER" : \
+(n) == PSI_T_RPAREN ? "RPAREN" : \
+(n) == PSI_T_BOOL ? "BOOL" : \
+(n) == PSI_T_FLOAT ? "FLOAT" : \
+(n) == PSI_T_STRING ? "STRING" : \
+(n) == PSI_T_CONST ? "CONST" : \
+(n) == PSI_T_NSNAME ? "NSNAME" : \
+(n) == PSI_T_EQUALS ? "EQUALS" : \
+(n) == PSI_T_TYPEDEF ? "TYPEDEF" : \
+(n) == PSI_T_VOID ? "VOID" : \
+(n) == PSI_T_LBRACKET ? "LBRACKET" : \
+(n) == PSI_T_RBRACKET ? "RBRACKET" : \
+(n) == PSI_T_COMMA ? "COMMA" : \
+(n) == PSI_T_ELLIPSIS ? "ELLIPSIS" : \
+(n) == PSI_T_DOUBLE ? "DOUBLE" : \
+(n) == PSI_T_INT8 ? "INT8" : \
+(n) == PSI_T_UINT8 ? "UINT8" : \
+(n) == PSI_T_INT16 ? "INT16" : \
+(n) == PSI_T_UINT16 ? "UINT16" : \
+(n) == PSI_T_INT32 ? "INT32" : \
+(n) == PSI_T_UINT32 ? "UINT32" : \
+(n) == PSI_T_INT64 ? "INT64" : \
+(n) == PSI_T_UINT64 ? "UINT64" : \
+(n) == PSI_T_FUNCTION ? "FUNCTION" : \
+(n) == PSI_T_NULL ? "NULL" : \
+(n) == PSI_T_TRUE ? "TRUE" : \
+(n) == PSI_T_FALSE ? "FALSE" : \
+(n) == PSI_T_DOLLAR ? "DOLLAR" : \
+(n) == PSI_T_CALLOC ? "CALLOC" : \
+(n) == PSI_T_OBJVAL ? "OBJVAL" : \
+(n) == PSI_T_ARRVAL ? "ARRVAL" : \
+(n) == PSI_T_PATHVAL ? "PATHVAL" : \
+(n) == PSI_T_STRLEN ? "STRLEN" : \
+(n) == PSI_T_STRVAL ? "STRVAL" : \
+(n) == PSI_T_FLOATVAL ? "FLOATVAL" : \
+(n) == PSI_T_INTVAL ? "INTVAL" : \
+(n) == PSI_T_BOOLVAL ? "BOOLVAL" : \
+(n) == PSI_T_TO_OBJECT ? "TO_OBJECT" : \
+(n) == PSI_T_TO_ARRAY ? "TO_ARRAY" : \
+(n) == PSI_T_TO_STRING ? "TO_STRING" : \
+(n) == PSI_T_TO_INT ? "TO_INT" : \
+(n) == PSI_T_TO_FLOAT ? "TO_FLOAT" : \
+(n) == PSI_T_TO_BOOL ? "TO_BOOL" : \
+(n) == PSI_T_MIXED ? "MIXED" : \
+(n) == PSI_T_ARRAY ? "ARRAY" : \
+(n) == PSI_T_OBJECT ? "OBJECT" : \
+(n) == PSI_T_AMPERSAND ? "AMPERSAND" : \
+<UNKNOWN>
+
 #define RETURN(t) do { \
        P->num = t; \
        if (P->flags & PSI_PARSER_DEBUG) { \
-               fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d)\n", P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF); \
+               fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \
+                               P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
+                               P->psi.file.fn, P->line, P->col); \
        } \
        return t; \
 } while(1)
 
+#define ADDCOLS \
+       P->col += P->cur - P->tok
+
+#define NEWLINE \
+       P->col = 1; \
+       ++P->line; \
+       goto nextline
+
 token_t PSI_ParserScan(PSI_Parser *P)
 {
        for (;;) {
+               ADDCOLS;
+       nextline:
                P->tok = P->cur;
                /*!re2c
                re2c:indent:top = 2;
@@ -167,7 +251,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                QUOTED_STRING = "\"" ([^\"])+ "\"";
                NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
 
-               ("#"|"//") .* "\n" { ++P->line; continue;}
+               ("#"|"//") .* "\n" { NEWLINE; }
                "(" {RETURN(PSI_T_LPAREN);}
                ")" {RETURN(PSI_T_RPAREN);}
                ";" {RETURN(PSI_T_EOS);}
@@ -184,7 +268,8 @@ token_t PSI_ParserScan(PSI_Parser *P)
                "+" {RETURN(PSI_T_PLUS);}
                "-" {RETURN(PSI_T_MINUS);}
                "/" {RETURN(PSI_T_SLASH);}
-               [\r\n] { ++P->line; continue; }
+               "..." {RETURN(PSI_T_ELLIPSIS);}
+               [\r\n] { NEWLINE; }
                [\t ]+ { continue; }
                'TRUE' {RETURN(PSI_T_TRUE);}
                'FALSE' {RETURN(PSI_T_FALSE);}
index 0ca3c4807cf03e78b1709707ae839315cc27ae48..30ad543c66178113ed9037f07224387b3362d669 100644 (file)
 #define PSI_T_LBRACKET                        32
 #define PSI_T_RBRACKET                        33
 #define PSI_T_COMMA                           34
-#define PSI_T_DOUBLE                          35
-#define PSI_T_INT8                            36
-#define PSI_T_UINT8                           37
-#define PSI_T_INT16                           38
-#define PSI_T_UINT16                          39
-#define PSI_T_INT32                           40
-#define PSI_T_UINT32                          41
-#define PSI_T_INT64                           42
-#define PSI_T_UINT64                          43
-#define PSI_T_FUNCTION                        44
-#define PSI_T_NULL                            45
-#define PSI_T_TRUE                            46
-#define PSI_T_FALSE                           47
-#define PSI_T_DOLLAR                          48
-#define PSI_T_CALLOC                          49
-#define PSI_T_OBJVAL                          50
-#define PSI_T_ARRVAL                          51
-#define PSI_T_PATHVAL                         52
-#define PSI_T_STRLEN                          53
-#define PSI_T_STRVAL                          54
-#define PSI_T_FLOATVAL                        55
-#define PSI_T_INTVAL                          56
-#define PSI_T_BOOLVAL                         57
-#define PSI_T_TO_OBJECT                       58
-#define PSI_T_TO_ARRAY                        59
-#define PSI_T_TO_STRING                       60
-#define PSI_T_TO_INT                          61
-#define PSI_T_TO_FLOAT                        62
-#define PSI_T_TO_BOOL                         63
-#define PSI_T_MIXED                           64
-#define PSI_T_ARRAY                           65
-#define PSI_T_OBJECT                          66
-#define PSI_T_AMPERSAND                       67
+#define PSI_T_ELLIPSIS                        35
+#define PSI_T_DOUBLE                          36
+#define PSI_T_INT8                            37
+#define PSI_T_UINT8                           38
+#define PSI_T_INT16                           39
+#define PSI_T_UINT16                          40
+#define PSI_T_INT32                           41
+#define PSI_T_UINT32                          42
+#define PSI_T_INT64                           43
+#define PSI_T_UINT64                          44
+#define PSI_T_FUNCTION                        45
+#define PSI_T_NULL                            46
+#define PSI_T_TRUE                            47
+#define PSI_T_FALSE                           48
+#define PSI_T_DOLLAR                          49
+#define PSI_T_CALLOC                          50
+#define PSI_T_OBJVAL                          51
+#define PSI_T_ARRVAL                          52
+#define PSI_T_PATHVAL                         53
+#define PSI_T_STRLEN                          54
+#define PSI_T_STRVAL                          55
+#define PSI_T_FLOATVAL                        56
+#define PSI_T_INTVAL                          57
+#define PSI_T_BOOLVAL                         58
+#define PSI_T_TO_OBJECT                       59
+#define PSI_T_TO_ARRAY                        60
+#define PSI_T_TO_STRING                       61
+#define PSI_T_TO_INT                          62
+#define PSI_T_TO_FLOAT                        63
+#define PSI_T_TO_BOOL                         64
+#define PSI_T_MIXED                           65
+#define PSI_T_ARRAY                           66
+#define PSI_T_OBJECT                          67
+#define PSI_T_AMPERSAND                       68
index 94cdf58556ec0ffdd86861bca3a88ed8eb075a24..7f38f178585f9d5673c426b3d3b31d36ecd303c7 100644 (file)
@@ -103,25 +103,29 @@ decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. {
 /* support opaque types */
 decl_typedef(def) ::= TYPEDEF VOID(V) NAME(ALIAS) EOS. {
        def = init_decl_typedef(ALIAS->text, init_decl_type(V->type, V->text));
-       free(V);
+       def->type->token = V;
+       //free(V);
        free(ALIAS);
 }
 decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. {
        def = init_decl_typedef(ALIAS->text, init_decl_type(S->type, N->text));
+       def->type->token = N;
        free(ALIAS);
        free(S);
-       free(N);
+       //free(N);
 }
 decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. {
        def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name));
+       def->type->token = ALIAS;
        def->type->strct = s;
-       free(ALIAS);
+       //free(ALIAS);
 }
 
 %type decl {decl*}
 %destructor decl {free_decl($$);}
 decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. {
        decl = init_decl(abi, func, args);
+
 }
 
 %type decl_func {decl_arg*}
@@ -135,7 +139,8 @@ decl_func(func) ::= VOID(T) NAME(N). {
                init_decl_type(T->type, T->text),
                init_decl_var(N->text, 0, 0)
        );
-       free(T);
+       func->type->token = T;
+       //free(T);
        free(N);
 }
 
@@ -178,7 +183,8 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). {
                init_decl_type(T->type, T->text),
                init_decl_var(N->text, p, 0)
        );
-       free(T);
+       arg_->type->token = T;
+       //free(T);
        free(N);
 }
 decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). {
@@ -186,7 +192,8 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). {
                init_decl_type(T->type, T->text),
                init_decl_var(N->text, p, 0)
        );
-       free(T);
+       arg_->type->token = T;
+       //free(T);
        free(N);
 }
 
@@ -200,6 +207,10 @@ decl_args(args) ::= decl_arg(arg). {
 decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). {
        args = add_decl_arg(args_, arg);
 }
+decl_args(args) ::= decl_args(args_) COMMA ELLIPSIS. {
+       args = args_;
+       args->varargs = 1;
+}
 %type struct_args {decl_args*}
 %destructor struct_args {free_decl_args($$);}
 struct_args(args) ::= struct_arg(arg). {
@@ -231,28 +242,32 @@ struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPARE
 %destructor decl_type {free_decl_type($$);}
 decl_type(type_) ::= decl_type_token(T). {
        type_ = init_decl_type(T->type, T->text);
-       free(T);
+       type_->token = T;
+       //free(T);
 }
 /* unsigned, urgh */
 decl_type(type_) ::= UNSIGNED NAME(T). {
        type_ = init_decl_type(T->type, T->text);
+       type_->token = T;
        type_->name = realloc(type_->name, T->size + sizeof("unsigned"));
        memmove(type_->name + sizeof("unsigned"), type_->name, T->size);
        memcpy(type_->name, "unsigned", sizeof("unsigned")-1);
        type_->name[sizeof("unsigned")] = ' ';
        type_->name[T->size + sizeof("unsigned")] = 0;
-       free(T);
+       //free(T);
 }
 /* we have to support plain int here because we have it in our lexer rules */
 decl_type(type_) ::= INT(T). {
        type_ = init_decl_type(PSI_T_NAME, T->text);
-       free(T);
+       type_->token = T;
+       //free(T);
 }
 /* structs ! */
 decl_type(type_) ::= STRUCT(S) NAME(T). {
        type_ = init_decl_type(S->type, T->text);
+       type_->token = T;
        free(S);
-       free(T);
+       //free(T);
 }
 
 %type const_decl_type {decl_type*}
@@ -309,6 +324,17 @@ impl_args(args) ::= LPAREN RPAREN. {
 impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. {
        args = args_;
 }
+impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. {
+       args = args_;
+       args->vararg = va;
+}
+
+%type impl_vararg {impl_arg*}
+%destructor impl_vararg {free_impl_arg($$);}
+impl_vararg(va) ::= impl_type(type) reference(r) ELLIPSIS DOLLAR NAME(T). {
+       va = init_impl_arg(type, init_impl_var(T->text, r), NULL);
+}
+
 %type impl_arg_list {impl_args*}
 %destructor impl_arg_list {free_impl_args($$);}
 impl_arg_list(args) ::= impl_arg(arg). {