#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"
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};
//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)
{
{
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");
eval = atoi(c->value);
}
+ if (notted)
+ eval = !eval;
+
QCC_PR_SimpleGetToken();
if (!strcmp(pr_token, "||"))
eval = ParsePrecompilerIf()||eval;
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...
{
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++;
{
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
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"))
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;
}
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);
}
num*=base;
num += c -'A'+10;
}
- else if (c == '.')
+ else if (c == '.' && pr_file_p[1]!='.')
{
pr_token[tokenlen++] = c;
pr_file_p++;
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;
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);
}
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++;
}
if (pr_file_p[1] == 0)
{
+ QCC_PR_ParseError(0, "EOF inside comment\n");
pr_file_p++;
return;
}
// 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);
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;
{
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;
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
{
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
{
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++)
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
{
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 ();
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);
else
printf ("warning: %s\n", string);
pr_warning_count++;
+
+ return true;
}
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);
*/
//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)
if (a->type != b->type)
return 1;
if (a->num_parms != b->num_parms)
+ {
return 1;
+ }
if (a->size != b->size)
return 1;
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;
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;
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)
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;
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;
{
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 (")");
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;
{
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)
}
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;
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;
}
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;
/* 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];
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;
// 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);
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;
}
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("{");
{
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(";"))
{
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(";");
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)
}
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("{");
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)
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];
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
{
{
type = QCC_PR_DuplicateType(type);
}
-
- return type;
}
+ return type;
}
#endif