]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/source/fteqcc-src/qcc_pr_lex.c
Update fteqcc source
[voretournament/voretournament.git] / misc / source / fteqcc-src / qcc_pr_lex.c
index 9bdd11c42d543d22c0c0e5a8f3ea069da45b7107..7a4319ba64ce795e16bcfe68c3cb3df93f76ae58 100644 (file)
@@ -6,22 +6,14 @@
 #endif
 #include "time.h"
 
-// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
-#ifdef __MINGW64__
-#ifndef QCCONLY
-       #if (_MSC_VER >= 1400)
-               //with MSVC 8, use MS extensions
-               #define snprintf linuxlike_snprintf_vc8
-               int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
-               #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
-       #else
-               //msvc crap
-               #define snprintf linuxlike_snprintf
-               int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
-               #define vsnprintf linuxlike_vsnprintf
-               int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
-       #endif
-#endif
+#ifdef _WIN64
+        #ifdef _SDL
+                #define snprintf linuxlike_snprintf
+                int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+                #define vsnprintf linuxlike_vsnprintf
+                int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
+                //void *__imp__vsnprintf = vsnprintf;
+        #endif
 #endif
 
 #define MEMBERFIELDNAME "__m%s"
@@ -82,6 +74,8 @@ QCC_type_t    *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void};
 QCC_type_t     *type_pointer;// = {ev_pointer/*, &def_pointer*/};
 QCC_type_t     *type_integer;// = {ev_integer/*, &def_integer*/};
 QCC_type_t     *type_variant;// = {ev_integer/*, &def_integer*/};
+QCC_type_t     *type_floatpointer;
+QCC_type_t     *type_intpointer;
 
 QCC_type_t     *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
 
@@ -106,13 +100,6 @@ void QCC_PR_LexWhitespace (void);
 
 //for compiler constants and file includes.
 
-typedef struct qcc_includechunk_s {
-       struct qcc_includechunk_s *prev;
-       char *filename;
-       char *currentdatapoint;
-       int currentlinenumber;
-       CompilerConstant_t *cnst;
-} qcc_includechunk_t;
 qcc_includechunk_t *currentchunk;
 void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
 {
@@ -237,16 +224,34 @@ int ParsePrecompilerIf(void)
 {
        CompilerConstant_t *c;
        int eval = 0;
-       //char *start = pr_file_p; //warning: unused variable âstartâ
+       pbool notted = false;
+       
+       /*skip whitespace*/
+       while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
+       {
+               pr_file_p++;
+       }
+       if (*pr_file_p == '!')
+       {
+               pr_file_p++;
+               notted = true;
+               while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
+               {
+                       pr_file_p++;
+               }
+       }
+
        if (!QCC_PR_SimpleGetToken())
        {
                if (*pr_file_p == '(')
                {
+                       pr_file_p++;
                        eval = ParsePrecompilerIf();
                        while (*pr_file_p == ' ' || *pr_file_p == '\t')
                                pr_file_p++;
                        if (*pr_file_p != ')')
                                QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n");
+                       pr_file_p++;
                }
                else
                        QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n");
@@ -280,6 +285,9 @@ int ParsePrecompilerIf(void)
                        eval = atoi(c->value);
        }
 
+       if (notted)
+               eval = !eval;
+
        QCC_PR_SimpleGetToken();
        if (!strcmp(pr_token, "||"))
                eval = ParsePrecompilerIf()||eval;
@@ -514,7 +522,7 @@ pbool QCC_PR_Precompiler(void)
                        for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
                                msg[a] = pr_file_p[a];
 
-                       msg[a-1] = '\0';
+                       msg[a] = '\0';
 
                        while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line, yes, I KNOW we are going to register an error, and not properly leave this function tree, but...
                        {
@@ -647,11 +655,6 @@ pbool QCC_PR_Precompiler(void)
                                if (*pr_file_p == '\r')
                                        pr_file_p++;
 
-                               for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
-                                       msg[a] = pr_file_p[a];
-
-                               msg[a-1] = '\0';
-
                                while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
                                {
                                        pr_file_p++;
@@ -831,6 +834,18 @@ pbool QCC_PR_Precompiler(void)
                        {
                                defaultstatic = atoi(msg);
                        }
+                       else if (!strncmp(qcc_token, "wrasm", 5))
+                       {
+                               pbool on = atoi(msg);
+
+                               if (asmfile && !on)
+                               {
+                                       fclose(asmfile);
+                                       asmfile = NULL;
+                               }                       
+                               if (!asmfile && on)
+                                       asmfile = fopen("qc.asm", "wb");
+                       }
                        else if (!strncmp(qcc_token, "sourcefile", 10))
                        {
        #define MAXSOURCEFILESLIST 8
@@ -847,7 +862,7 @@ pbool QCC_PR_Precompiler(void)
                                        if (!strcmp(sourcefileslist[i], qcc_token))
                                                break;
                                }
-                               if (i == numsourcefiles)
+                               if (i == numsourcefiles && numsourcefiles < MAXSOURCEFILESLIST)
                                        strcpy(sourcefileslist[numsourcefiles++], qcc_token);
                        }
                        else if (!QC_strcasecmp(qcc_token, "TARGET"))
@@ -857,7 +872,7 @@ pbool QCC_PR_Precompiler(void)
                                else if (!QC_strcasecmp(msg, "H2") || !QC_strcasecmp(msg, "HEXEN2"))
                                {
                                        if (numstatements)
-                                               QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
+                                               QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch to hexen2 target \'%s\'. Ignored.", msg);
                                        else
                                                qcc_targetformat = QCF_HEXEN2;
                                }
@@ -1354,7 +1369,7 @@ int QCC_PR_LexInteger (void)
                len++;
                pr_file_p++;
                c = *pr_file_p;
-       } while ((c >= '0' && c<= '9') || c == '.' || (c>='a' && c <= 'f'));
+       } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.') || (c>='a' && c <= 'f'));
        pr_token[len] = 0;
        return atoi (pr_token);
 }
@@ -1407,7 +1422,7 @@ void QCC_PR_LexNumber (void)
                        num*=base;
                        num += c -'A'+10;
                }
-               else if (c == '.')
+               else if (c == '.' && pr_file_p[1]!='.')
                {
                        pr_token[tokenlen++] = c;
                        pr_file_p++;
@@ -1434,6 +1449,15 @@ void QCC_PR_LexNumber (void)
                        pr_immediate._float = (float)atof(pr_token);
                        return;
                }
+               else if (c == 'f')
+               {
+                       pr_token[tokenlen++] = c;
+                       pr_token[tokenlen++] = 0;
+                       pr_file_p++;
+                       pr_immediate_type = type_float;
+                       pr_immediate._float = num*sign;
+                       return;
+               }
                else if (c == 'i')
                {
                        pr_token[tokenlen++] = c;
@@ -1487,6 +1511,8 @@ float QCC_PR_LexFloat (void)
                pr_file_p++;
                c = *pr_file_p;
        } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.'));       //only allow a . if the next isn't too...
+       if (*pr_file_p == 'f')
+               pr_file_p++;
        pr_token[len] = 0;
        return (float)atof (pr_token);
 }
@@ -1532,6 +1558,7 @@ void QCC_PR_LexVector (void)
                default:
                        QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
                }
+               pr_file_p++;
                if (*pr_file_p != '\'')
                        QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
                pr_file_p++;
@@ -1680,6 +1707,7 @@ void QCC_PR_LexWhitespace (void)
                                }
                                if (pr_file_p[1] == 0)
                                {
+                                       QCC_PR_ParseError(0, "EOF inside comment\n");
                                        pr_file_p++;
                                        return;
                                }
@@ -1964,7 +1992,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name)
 //     if (numCompilerConstants >= MAX_CONSTANTS)
 //             QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
 
-       if (strlen(name) >= MAXCONSTANTLENGTH || !*name)
+       if (strlen(name) >= MAXCONSTANTNAMELENGTH || !*name)
                QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short");
 
        cnst = pHash_Get(&compconstantstable, name);
@@ -2112,6 +2140,43 @@ void QCC_PR_ConditionCompilation(void)
        pr_file_p = s;
 }
 
+/* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */
+static void QCC_PR_ExpandStrCat(char **buffer, int *bufferlen, int *buffermax,   char *newdata, int newlen)
+{
+       int newmax = *bufferlen + newlen;
+       if (newmax < *bufferlen)
+       {
+               QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
+               return;
+       }
+       if (newmax > *buffermax)
+       {
+               char *newbuf;
+               if (newmax < 64)
+                       newmax = 64;
+               if (newmax < *bufferlen * 2)
+               {
+                       newmax = *bufferlen * 2;
+                       if (newmax < *bufferlen) /*overflowed?*/
+                       {
+                               QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
+                               return;
+                       }
+               }
+               newbuf = realloc(*buffer, newmax);
+               if (!newbuf)
+               {
+                       QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
+                       return; /*OOM*/
+               }
+               *buffer = newbuf;
+               *buffermax = newmax;
+       }
+       memcpy(*buffer + *bufferlen, newdata, newlen);
+       *bufferlen += newlen;
+       /*no null terminator, remember to cat one if required*/
+}
+
 int QCC_PR_CheakCompConst(void)
 {
        char            *oldpr_file_p = pr_file_p;
@@ -2165,7 +2230,10 @@ int QCC_PR_CheakCompConst(void)
                        {
                                int p;
                                char *start;
-                               char buffer[1024];
+                               char *starttok;
+                               char *buffer;
+                               int buffermax;
+                               int bufferlen;
                                char *paramoffset[MAXCONSTANTPARAMS+1];
                                int param=0;
                                int plevel=0;
@@ -2220,38 +2288,45 @@ int QCC_PR_CheakCompConst(void)
                                        QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters");
                                paramoffset[param] = start;
 
-                               *buffer = '\0';
+                               buffer = NULL;
+                               bufferlen = 0;
+                               buffermax = 0;
 
                                oldpr_file_p = pr_file_p;
                                pr_file_p = c->value;
                                for(;;)
                                {
-                                       whitestart = p = strlen(buffer);
+                                       whitestart = bufferlen;
+                                       starttok = pr_file_p;
                                        while(*pr_file_p <= ' ')        //copy across whitespace
                                        {
                                                if (!*pr_file_p)
                                                        break;
-                                               buffer[p++] = *pr_file_p++;
+                                               pr_file_p++;
+                                       }
+                                       if (starttok != pr_file_p)
+                                       {
+                                               QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   starttok, pr_file_p - starttok);
                                        }
-                                       buffer[p] = 0;
 
                                        if(*pr_file_p == '\"')
                                        {
+                                               starttok = pr_file_p;
                                                do
                                                {
-                                                       buffer[p++] = *pr_file_p;
-                                                       ++pr_file_p;
+                                                       pr_file_p++;
                                                } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
-                                               buffer[p++] = *pr_file_p; // copy the end-quote too
-                                               buffer[p] = 0;
-                                               ++pr_file_p; // and skip it
+                                               if(*pr_file_p == '\"')
+                                                       pr_file_p++;
+
+                                               QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   starttok, pr_file_p - starttok);
                                                continue;
                                        }
                                        else if (*pr_file_p == '#')     //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
                                        {
                                                if (pr_file_p[1] == '#')
-                                               {       //concatinate (srip out whitespace)
-                                                       buffer[whitestart] = '\0';
+                                               {       //concatinate (strip out whitespace before the token)
+                                                       bufferlen = whitestart;
                                                        pr_file_p+=2;
                                                }
                                                else
@@ -2265,16 +2340,16 @@ int QCC_PR_CheakCompConst(void)
                                                        {
                                                                if (!STRCMP(qcc_token, c->params[p]))
                                                                {
-                                                                       strcat(buffer, "\"");
-                                                                       strcat(buffer, paramoffset[p]);
-                                                                       strcat(buffer, "\"");
+                                                                       QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\"", 1);
+                                                                       QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   paramoffset[p], strlen(paramoffset[p]));
+                                                                       QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\"", 1);
                                                                        break;
                                                                }
                                                        }
                                                        if (p == param)
                                                        {
-                                                               strcat(buffer, "#");
-                                                               strcat(buffer, qcc_token);
+                                                               QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "#", 1);
+                                                               QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   qcc_token, strlen(qcc_token));
                                                                //QCC_PR_ParseWarning(0, "Stringification ignored");
                                                        }
                                                        continue;       //already did this one
@@ -2289,12 +2364,12 @@ int QCC_PR_CheakCompConst(void)
                                        {
                                                if (!STRCMP(qcc_token, c->params[p]))
                                                {
-                                                       strcat(buffer, paramoffset[p]);
+                                                       QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   paramoffset[p], strlen(paramoffset[p]));
                                                        break;
                                                }
                                        }
                                        if (p == param)
-                                               strcat(buffer, qcc_token);
+                                               QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   qcc_token, strlen(qcc_token));
                                }
 
                                for (p = 0; p < param-1; p++)
@@ -2302,12 +2377,17 @@ int QCC_PR_CheakCompConst(void)
                                paramoffset[p][strlen(paramoffset[p])] = ')';
 
                                pr_file_p = oldpr_file_p;
-                               if (!*buffer)
+                               if (!bufferlen)
                                        expandedemptymacro = true;
-                               QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
+                               else
+                               {
+                                       QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\0", 1);
+                                       QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
+                               }
+                               free(buffer);
                        }
                        else
-                               QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without opening brace");
+                               QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list");
                }
                else
                {
@@ -2495,7 +2575,7 @@ void QCC_PR_Lex (void)
                QCC_PR_LexNumber();
                return;
        }
-       if ( (c == '.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
+       if ( (c == '.'&&pr_file_p[1]!='.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
        {
                pr_token_type = tt_immediate;
                QCC_PR_LexNumber ();
@@ -2688,13 +2768,13 @@ void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
                printf ("note: %s\n", string);
 }
 
-void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
+pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
 {
        va_list         argptr;
        char            string[1024];
 
        if (qccwarningdisabled[type])
-               return;
+               return false;
 
        va_start (argptr,error);
        QC_vsnprintf (string,sizeof(string)-1, error,argptr);
@@ -2711,6 +2791,8 @@ void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
        else
                printf ("warning: %s\n", string);
        pr_warning_count++;
+
+       return true;
 }
 
 
@@ -2816,7 +2898,12 @@ char *QCC_PR_ParseName (void)
        char *ret;
 
        if (pr_token_type != tt_name)
-               QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
+       {
+               if (pr_token_type == tt_eof)
+                       QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token);
+               else
+                       QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
+       }
        if (strlen(pr_token) >= MAX_NAME-1)
                QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long");
        strcpy (ident, pr_token);
@@ -2838,7 +2925,6 @@ a new one and copies it out.
 */
 
 //0 if same
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
 int typecmp(QCC_type_t *a, QCC_type_t *b)
 {
        if (a == b)
@@ -2849,7 +2935,9 @@ int typecmp(QCC_type_t *a, QCC_type_t *b)
        if (a->type != b->type)
                return 1;
        if (a->num_parms != b->num_parms)
+       {
                return 1;
+       }
 
        if (a->size != b->size)
                return 1;
@@ -2883,7 +2971,7 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
        if (!in)
                return NULL;
 
-       out = QCC_PR_NewType(in->name, in->type);
+       out = QCC_PR_NewType(in->name, in->type, false);
        out->aux_type = QCC_PR_DuplicateType(in->aux_type);
        out->param = QCC_PR_DuplicateType(in->param);
        ip = in->param;
@@ -2896,6 +2984,7 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
                        op = (op->next = QCC_PR_DuplicateType(ip));
                ip = ip->next;
        }
+       out->arraysize = in->arraysize;
        out->size = in->size;
        out->num_parms = in->num_parms;
        out->ofs = in->ofs;
@@ -2923,17 +3012,29 @@ char *TypeName(QCC_type_t *type)
 
        if (type->type == ev_function)
        {
+               pbool varg = type->num_parms < 0;
+               int args = type->num_parms;
+               if (args < 0)
+                       args = -(args+1);
                strcat(ret, type->aux_type->name);
                strcat(ret, " (");
                type = type->param;
                while(type)
                {
+                       if (args<=0)
+                               strcat(ret, "optional ");
+                       args--;
+
                        strcat(ret, type->name);
                        type = type->next;
 
-                       if (type)
+                       if (type || varg)
                                strcat(ret, ", ");
                }
+               if (varg)
+               {
+                       strcat(ret, "...");
+               }
                strcat(ret, ")");
        }
        else if (type->type == ev_entity && type->parentclass)
@@ -3060,17 +3161,18 @@ char    pr_parm_names[MAX_PARMS][MAX_NAME];
 
 pbool recursivefunctiontype;
 
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
 //expects a ( to have already been parsed.
 QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
 {
        QCC_type_t      *ftype, *ptype, *nptype;
        char    *name;
        int definenames = !recursivefunctiontype;
+       int optional = 0;
+       int numparms = 0;
 
        recursivefunctiontype++;
 
-       ftype = QCC_PR_NewType(type_function->name, ev_function);
+       ftype = QCC_PR_NewType(type_function->name, ev_function, false);
 
        ftype->aux_type = returntype;   // return type
        ftype->num_parms = 0;
@@ -3089,11 +3191,21 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
 
                                if (QCC_PR_CheckToken ("..."))
                                {
-                                       ftype->num_parms = (ftype->num_parms * -1) - 1;
+                                       if (optional)
+                                               numparms = optional-1;
+                                       ftype->num_parms = (numparms * -1) - 1;
                                        break;
                                }
 
-                               nptype = QCC_PR_ParseType(true);
+                               if (QCC_PR_CheckKeyword(keyword_optional, "optional"))
+                               {
+                                       if (!optional)
+                                               optional = numparms+1;
+                               }
+                               else if (optional)
+                                       QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n");
+
+                               nptype = QCC_PR_ParseType(true, false);
 
                                if (nptype->type == ev_void)
                                        break;
@@ -3114,11 +3226,15 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
                                {
                                        name = QCC_PR_ParseName ();
                                        if (definenames)
-                                               strcpy (pr_parm_names[ftype->num_parms], name);
+                                               strcpy (pr_parm_names[numparms], name);
                                }
                                else if (definenames)
-                                       strcpy (pr_parm_names[ftype->num_parms], "");
-                               ftype->num_parms++;
+                                       strcpy (pr_parm_names[numparms], "");
+                               numparms++;
+                               if (optional)
+                                       ftype->num_parms = optional-1;
+                               else
+                                       ftype->num_parms = numparms;
                        } while (QCC_PR_CheckToken (","));
 
                QCC_PR_Expect (")");
@@ -3137,7 +3253,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
 
        recursivefunctiontype++;
 
-       ftype = QCC_PR_NewType(type_function->name, ev_function);
+       ftype = QCC_PR_NewType(type_function->name, ev_function, false);
 
        ftype->aux_type = returntype;   // return type
        ftype->num_parms = 0;
@@ -3164,19 +3280,19 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
                                {
                                        sprintf(argname, "arg%i", ftype->num_parms);
                                        name = argname;
-                                       nptype = QCC_PR_NewType("Variant", ev_variant);
+                                       nptype = QCC_PR_NewType("Variant", ev_variant, false);
                                }
                                else if (QCC_PR_CheckName("vect"))      //this can only be of vector sizes, so...
                                {
                                        sprintf(argname, "arg%i", ftype->num_parms);
                                        name = argname;
-                                       nptype = QCC_PR_NewType("Vector", ev_vector);
+                                       nptype = QCC_PR_NewType("Vector", ev_vector, false);
                                }
                                else
                                {
                                        name = QCC_PR_ParseName();
                                        QCC_PR_Expect(":");
-                                       nptype = QCC_PR_ParseType(true);
+                                       nptype = QCC_PR_ParseType(true, false);
                                }
 
                                if (nptype->type == ev_void)
@@ -3207,26 +3323,34 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
 }
 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
 {
-       QCC_type_t      *ptype;
-       char name[128];
-       sprintf(name, "*%s", pointsto->name);
-       ptype = QCC_PR_NewType(name, ev_pointer);
+       QCC_type_t      *ptype, *e;
+       ptype = QCC_PR_NewType("ptr", ev_pointer, false);
        ptype->aux_type = pointsto;
-       return QCC_PR_FindType (ptype);
+       e = QCC_PR_FindType (ptype);
+       if (e == ptype)
+       {
+               char name[128];
+               sprintf(name, "ptr to %s", pointsto->name);
+               e->name = strdup(name);
+       }
+       return e;
 }
 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
 {
        QCC_type_t      *ptype;
        char name[128];
        sprintf(name, "FIELD TYPE(%s)", pointsto->name);
-       ptype = QCC_PR_NewType(name, ev_field);
+       ptype = QCC_PR_NewType(name, ev_field, false);
        ptype->aux_type = pointsto;
        ptype->size = ptype->aux_type->size;
        return QCC_PR_FindType (ptype);
 }
 
 pbool type_inlinefunction;
-QCC_type_t *QCC_PR_ParseType (int newtype)
+/*newtype=true: creates a new type always
+  silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL
+*/
+QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
 {
        QCC_type_t      *newparm;
        QCC_type_t      *newt;
@@ -3240,14 +3364,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
 
        if (QCC_PR_CheckToken (".."))   //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
        {
-               newt = QCC_PR_NewType("FIELD TYPE", ev_field);
-               newt->aux_type = QCC_PR_ParseType (false);
+               newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
+               newt->aux_type = QCC_PR_ParseType (false, false);
 
                newt->size = newt->aux_type->size;
 
                newt = QCC_PR_FindType (newt);
 
-               type = QCC_PR_NewType("FIELD TYPE", ev_field);
+               type = QCC_PR_NewType("FIELD TYPE", ev_field, false);
                type->aux_type = newt;
 
                type->size = type->aux_type->size;
@@ -3258,8 +3382,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
        }
        if (QCC_PR_CheckToken ("."))
        {
-               newt = QCC_PR_NewType("FIELD TYPE", ev_field);
-               newt->aux_type = QCC_PR_ParseType (false);
+               newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
+               newt->aux_type = QCC_PR_ParseType (false, false);
 
                newt->size = newt->aux_type->size;
 
@@ -3286,6 +3410,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                /* Look to see if this type is already defined */
                for(i=0;i<numtypeinfos;i++)
                {
+                       if (!qcc_typeinfo[i].typedefed)
+                               continue;
                        if (STRCMP(qcc_typeinfo[i].name, classname) == 0)
                        {
                                newt = &qcc_typeinfo[i];
@@ -3300,7 +3426,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                        QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname);
 
                if (!newt)
-                       newt = QCC_PR_NewType(classname, ev_entity);
+                       newt = QCC_PR_NewType(classname, ev_entity, true);
 
                newt->size=type_entity->size;
 
@@ -3333,7 +3459,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
 //                     if (QCC_PR_CheckToken(","))
 //                             type->next = QCC_PR_NewType(type->name, type->type);
 //                     else
-                               newparm = QCC_PR_ParseType(true);
+                               newparm = QCC_PR_ParseType(true, false);
 
                        if (newparm->type == ev_struct || newparm->type == ev_union)    //we wouldn't be able to handle it.
                                QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname);
@@ -3354,10 +3480,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                                newparm->name = QCC_CopyString("")+strings;
 
                        sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name);
-                       fieldtype = QCC_PR_NewType(newparm->name, ev_field);
+                       fieldtype = QCC_PR_NewType(newparm->name, ev_field, false);
                        fieldtype->aux_type = newparm;
                        fieldtype->size = newparm->size;
-                       QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 1, false);
+                       QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false);
 
 
                        newparm->ofs = 0;//newt->size;
@@ -3377,7 +3503,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
        }
        if (QCC_PR_CheckKeyword (keyword_struct, "struct"))
        {
-               newt = QCC_PR_NewType("struct", ev_struct);
+               newt = QCC_PR_NewType("struct", ev_struct, false);
                newt->size=0;
                QCC_PR_Expect("{");
 
@@ -3392,10 +3518,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                        {
                                if (!newparm)
                                        QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
-                               newparm = QCC_PR_NewType(newparm->name, newparm->type);
+                               newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
                        }
                        else
-                               newparm = QCC_PR_ParseType(true);
+                               newparm = QCC_PR_ParseType(true, false);
 
                        if (!QCC_PR_CheckToken(";"))
                        {
@@ -3403,8 +3529,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                                QCC_PR_Lex();
                                if (QCC_PR_CheckToken("["))
                                {
-                                       newparm->size*=atoi(pr_token);
-                                       QCC_PR_Lex();
+                                       newparm->arraysize=QCC_PR_IntConstExpr();
                                        QCC_PR_Expect("]");
                                }
                                QCC_PR_CheckToken(";");
@@ -3412,7 +3537,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                        else
                                newparm->name = QCC_CopyString("")+strings;
                        newparm->ofs = newt->size;
-                       newt->size += newparm->size;
+                       newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1);
                        newt->num_parms++;
 
                        if (type)
@@ -3425,7 +3550,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
        }
        if (QCC_PR_CheckKeyword (keyword_union, "union"))
        {
-               newt = QCC_PR_NewType("union", ev_union);
+               newt = QCC_PR_NewType("union", ev_union, false);
                newt->size=0;
                QCC_PR_Expect("{");
 
@@ -3435,25 +3560,34 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                newparm = NULL;
                while (!QCC_PR_CheckToken("}"))
                {
+                       int arraysize;
                        if (QCC_PR_CheckToken(","))
                        {
                                if (!newparm)
                                        QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
-                               newparm = QCC_PR_NewType(newparm->name, newparm->type);
+                               newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
                        }
                        else
-                               newparm = QCC_PR_ParseType(true);
+                               newparm = QCC_PR_ParseType(true, false);
                        if (QCC_PR_CheckToken(";"))
                                newparm->name = QCC_CopyString("")+strings;
                        else
                        {
                                newparm->name = QCC_CopyString(pr_token)+strings;
                                QCC_PR_Lex();
+                               if (QCC_PR_CheckToken("["))
+                               {
+                                       newparm->arraysize=QCC_PR_IntConstExpr();
+                                       QCC_PR_Expect("]");
+                               }
                                QCC_PR_Expect(";");
                        }
                        newparm->ofs = 0;
-                       if (newparm->size > newt->size)
-                               newt->size = newparm->size;
+                       arraysize = newparm->arraysize;
+                       if (!arraysize)
+                               arraysize = 1;
+                       if (newparm->size*arraysize > newt->size)
+                               newt->size = newparm->size*arraysize;
                        newt->num_parms++;
 
                        if (type)
@@ -3467,6 +3601,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
        type = NULL;
        for (i = 0; i < numtypeinfos; i++)
        {
+               if (!qcc_typeinfo[i].typedefed)
+                       continue;
                if (!STRCMP(qcc_typeinfo[i].name, name))
                {
                        type = &qcc_typeinfo[i];
@@ -3492,16 +3628,22 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                        type = type_function;
                else
                {
+                       if (silentfail)
+                               return NULL;
+
                        QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
                        type = type_float;      // shut up compiler warning
                }
        }
        QCC_PR_Lex ();
 
+       while (QCC_PR_CheckToken("*"))
+               type = QCC_PointerTypeTo(type);
+
        if (QCC_PR_CheckToken ("("))    //this is followed by parameters. Must be a function.
        {
                type_inlinefunction = true;
-               return QCC_PR_ParseFunctionType(newtype, type);
+               type = QCC_PR_ParseFunctionType(newtype, type);
        }
        else
        {
@@ -3509,9 +3651,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
                {
                        type = QCC_PR_DuplicateType(type);
                }
-
-               return type;
        }
+       return type;
 }
 
 #endif