-/*
- * declare.c
- *
- * Ullrich von Bassewitz, 20.06.1998
- */
+/*****************************************************************************/
+/* */
+/* declare.c */
+/* */
+/* Parse variable and function declarations */
+/* */
+/* */
+/* */
+/* (C) 1998-2001 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include <ctype.h>
/* common */
#include "xmalloc.h"
#include "anonname.h"
#include "codegen.h"
#include "datatype.h"
+#include "declattr.h"
#include "error.h"
#include "expr.h"
#include "funcdesc.h"
static type OptionalQualifiers (type Q)
/* Read type qualifiers if we have any */
{
- while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
+ while (CurTok.Tok == TOK_CONST || CurTok.Tok == TOK_VOLATILE) {
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_CONST:
if (Q & T_QUAL_CONST) {
- Error (ERR_DUPLICATE_QUALIFIER, "const");
+ Error ("Duplicate qualifier: `const'");
}
Q |= T_QUAL_CONST;
break;
case TOK_VOLATILE:
if (Q & T_QUAL_VOLATILE) {
- Error (ERR_DUPLICATE_QUALIFIER, "volatile");
+ Error ("Duplicate qualifier: `volatile'");
}
Q |= T_QUAL_VOLATILE;
break;
static void optionalint (void)
/* Eat an optional "int" token */
{
- if (curtok == TOK_INT) {
+ if (CurTok.Tok == TOK_INT) {
/* Skip it */
NextToken ();
}
static void optionalsigned (void)
/* Eat an optional "signed" token */
{
- if (curtok == TOK_SIGNED) {
+ if (CurTok.Tok == TOK_SIGNED) {
/* Skip it */
NextToken ();
}
D->Flags &= ~DS_DEF_STORAGE;
/* Check the storage class given */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_EXTERN:
D->StorageClass = SC_EXTERN | SC_STATIC;
ident Ident;
/* Accept forward definitions */
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
return;
}
/* Read the enum tags */
EnumVal = 0;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
/* We expect an identifier */
- if (curtok != TOK_IDENT) {
- Error (ERR_IDENT_EXPECTED);
+ if (CurTok.Tok != TOK_IDENT) {
+ Error ("Identifier expected");
continue;
}
NextToken ();
/* Check for an assigned value */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
struct expent lval;
NextToken ();
constexpr (&lval);
}
/* Add an entry to the symbol table */
- AddEnumSym (Ident, EnumVal++);
+ AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
/* Check for end of definition */
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
SymEntry* Entry;
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
/* Just a forward declaration. Try to find a struct with the given
* name. If there is none, insert a forward declaration into the
* current lexical level.
Entry = AddStructSym (Name, 0, 0);
} else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
/* Already defined in the level but no struct */
- Error (ERR_SYMBOL_KIND);
+ Error ("Symbol `%s' is already different kind", Name);
}
return Entry;
}
/* Parse struct fields */
Size = 0;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
DeclSpec Spec;
}
}
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
/* Look at the data type */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_VOID:
NextToken ();
case TOK_LONG:
NextToken ();
- if (curtok == TOK_UNSIGNED) {
+ if (CurTok.Tok == TOK_UNSIGNED) {
NextToken ();
optionalint ();
D->Type[0] = T_ULONG;
case TOK_SHORT:
NextToken ();
- if (curtok == TOK_UNSIGNED) {
+ if (CurTok.Tok == TOK_UNSIGNED) {
NextToken ();
optionalint ();
D->Type[0] = T_USHORT;
case TOK_SIGNED:
NextToken ();
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_CHAR:
NextToken ();
- D->Type[0] = T_CHAR;
+ D->Type[0] = T_SCHAR;
D->Type[1] = T_END;
break;
case TOK_UNSIGNED:
NextToken ();
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_CHAR:
NextToken ();
case TOK_STRUCT:
case TOK_UNION:
- StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
+ StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
NextToken ();
/* */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
strcpy (Ident, CurTok.Ident);
NextToken ();
} else {
case TOK_ENUM:
NextToken ();
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
/* Named enum */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
/* Find an entry with this name */
Entry = FindTagSym (CurTok.Ident);
if (Entry) {
if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
- Error (ERR_SYMBOL_KIND);
+ Error ("Symbol `%s' is already different kind", Entry->Name);
}
} else {
/* Insert entry into table ### */
/* Skip the identifier */
NextToken ();
} else {
- Error (ERR_IDENT_EXPECTED);
+ Error ("Identifier expected");
}
}
/* Remember we have an extra type decl */
default:
if (Default < 0) {
- Error (ERR_TYPE_EXPECTED);
+ Error ("Type expected");
D->Type[0] = T_INT;
D->Type[1] = T_END;
} else {
/* Parse an old style (K&R) parameter list */
{
/* Parse params */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
/* List of identifiers expected */
- if (curtok != TOK_IDENT) {
- Error (ERR_IDENT_EXPECTED);
+ if (CurTok.Tok != TOK_IDENT) {
+ Error ("Identifier expected");
}
/* Create a symbol table entry with type int */
NextToken ();
/* Check for more parameters */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
ConsumeRParen ();
/* An optional list of type specifications follows */
- while (curtok != TOK_LCURLY) {
+ while (CurTok.Tok != TOK_LCURLY) {
- DeclSpec Spec;
+ DeclSpec Spec;
/* Read the declaration specifier */
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
*/
if ((Spec.StorageClass & SC_AUTO) == 0 &&
(Spec.StorageClass & SC_REGISTER) == 0) {
- Error (ERR_ILLEGAL_STORAGE_CLASS);
+ Error ("Illegal storage class");
}
/* Parse a comma separated variable list */
/* Found it, change the default type to the one given */
ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
} else {
- Error (ERR_UNKNOWN_IDENT, Decl.Ident);
+ Error ("Unknown identifier: `%s'", Decl.Ident);
}
}
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
/* Parse a new style (ANSI) parameter list */
{
/* Parse params */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
DeclSpec Spec;
Declaration Decl;
-
+ DeclAttr Attr;
/* Allow an ellipsis as last parameter */
- if (curtok == TOK_ELLIPSIS) {
+ if (CurTok.Tok == TOK_ELLIPSIS) {
NextToken ();
- F->Flags |= FD_ELLIPSIS;
+ F->Flags |= FD_VARIADIC;
break;
}
*/
if ((Spec.StorageClass & SC_AUTO) == 0 &&
(Spec.StorageClass & SC_REGISTER) == 0) {
- Error (ERR_ILLEGAL_STORAGE_CLASS);
+ Error ("Illegal storage class");
}
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
Spec.StorageClass &= ~SC_DEF;
}
+ /* Parse an attribute ### */
+ ParseAttribute (&Decl, &Attr);
+
/* Create a symbol table entry */
AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
++F->ParamCount;
/* Check for more parameters */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
ConsumeRParen ();
/* Check if this is a function definition */
- if (curtok == TOK_LCURLY) {
+ if (CurTok.Tok == TOK_LCURLY) {
/* Print an error if in strict ANSI mode and we have unnamed
* parameters.
*/
if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
- Error (ERR_MISSING_PARAM_NAME);
+ Error ("Parameter name omitted");
}
}
}
EnterFunctionLevel ();
/* Check for several special parameter lists */
- if (curtok == TOK_RPAREN) {
+ if (CurTok.Tok == TOK_RPAREN) {
/* Parameter list is empty */
- F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
- } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
+ F->Flags |= (FD_EMPTY | FD_VARIADIC);
+ } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
/* Parameter list declared as void */
NextToken ();
F->Flags |= FD_VOID_PARAM;
- } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
- /* Old style (K&R) function. Assume variable param list. */
- F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
+ } else if (CurTok.Tok == TOK_IDENT &&
+ (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
+ /* If the identifier is a typedef, we have a new style parameter list,
+ * if it's some other identifier, it's an old style parameter list.
+ */
+ Sym = FindSym (CurTok.Ident);
+ if (Sym == 0 || !IsTypeDef (Sym)) {
+ /* Old style (K&R) function. Assume variable param list. */
+ F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
+ }
}
/* Parse params */
/* Assign offsets. If the function has a variable parameter list,
* there's one additional byte (the arg size).
*/
- Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
+ Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
Sym = GetSymTab()->SymTail;
while (Sym) {
unsigned Size = SizeOf (Sym->Type);
/* Recursively process declarators. Build a type array in reverse order. */
{
- if (curtok == TOK_STAR) {
+ if (CurTok.Tok == TOK_STAR) {
type T = T_PTR;
NextToken ();
/* Allow optional const or volatile qualifiers */
Decl (D, Mode);
*D->T++ = T;
return;
- } else if (curtok == TOK_LPAREN) {
+ } else if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
Decl (D, Mode);
ConsumeRParen ();
- } else if (curtok == TOK_FASTCALL) {
+ } else if (CurTok.Tok == TOK_FASTCALL) {
/* Remember the current type pointer */
type* T = D->T;
/* Skip the fastcall token */
Decl (D, Mode);
/* Set the fastcall flag */
if (!IsTypeFunc (T)) {
- Error (ERR_ILLEGAL_MODIFIER);
+ Error ("__fastcall__ modifier applied to non function");
+ } else if (IsVariadicFunc (T)) {
+ Error ("Cannot apply __fastcall__ to functions with variable parameter list");
} else {
- FuncDesc* F = DecodePtr (T+1);
+ FuncDesc* F = (FuncDesc*) DecodePtr (T+1);
F->Flags |= FD_FASTCALL;
}
return;
*/
if (Mode == DM_NO_IDENT) {
D->Ident[0] = '\0';
- } else if (curtok == TOK_IDENT) {
+ } else if (CurTok.Tok == TOK_IDENT) {
strcpy (D->Ident, CurTok.Ident);
NextToken ();
} else {
if (Mode == DM_NEED_IDENT) {
- Error (ERR_IDENT_EXPECTED);
+ Error ("Identifier expected");
}
D->Ident[0] = '\0';
return;
}
}
- while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
- if (curtok == TOK_LPAREN) {
+ while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
/* Function declaration */
FuncDesc* F;
NextToken ();
unsigned long Size = 0;
NextToken ();
/* Read the size if it is given */
- if (curtok != TOK_RBRACK) {
+ if (CurTok.Tok != TOK_RBRACK) {
struct expent lval;
constexpr (&lval);
Size = lval.e_const;
/* Check the size of the generated type */
if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
- Error (ERR_ILLEGAL_SIZE);
+ if (D->Ident[0] != '\0') {
+ Error ("Size of `%s' is invalid", D->Ident);
+ } else {
+ Error ("Invalid size");
+ }
}
}
*/
{
if ((D->Flags & DS_EXTRA_TYPE) == 0) {
- Warning (WARN_USELESS_DECL);
+ Warning ("Useless declaration");
}
}
break;
default:
- Error (ERR_ILLEGAL_TYPE);
+ Error ("Illegal type in initialization");
break;
}
- if (curtok != TOK_COMMA) {
+ if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
- } while (curtok != TOK_RCURLY);
+ } while (CurTok.Tok != TOK_RCURLY);
ConsumeRCurly ();
}
*/
Tab = Entry->V.S.SymTab;
if (Tab == 0) {
- Error (ERR_INIT_INCOMPLETE_TYPE);
+ Error ("Cannot initialize variables with incomplete type");
/* Returning here will cause lots of errors, but recovery is difficult */
return;
}
/* Get a pointer to the list of symbols */
Entry = Tab->SymHead;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
if (Entry == 0) {
- Error (ERR_TOO_MANY_INITIALIZERS);
+ Error ("Too many initializers");
return;
}
ParseInit (Entry->Type);
Entry = Entry->NextSym;
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
void ParseInit (type* T)
/* Parse initialization of variables. */
{
- int count;
struct expent lval;
type* t;
const char* str;
- int sz;
+ int Count;
+ int Size;
switch (UnqualifiedType (*T)) {
break;
case T_ARRAY:
- sz = Decode (T + 1);
+ Size = Decode (T + 1);
t = T + DECODE_SIZE + 1;
- if (IsTypeChar(t) && curtok == TOK_SCONST) {
- str = GetLiteral (curval);
- count = strlen (str) + 1;
- TranslateLiteralPool (curval); /* Translate into target charset */
- g_defbytes (str, count);
- ResetLiteralOffs (curval); /* Remove string from pool */
+ if (IsTypeChar(t) && CurTok.Tok == TOK_SCONST) {
+ str = GetLiteral (CurTok.IVal);
+ Count = strlen (str) + 1;
+ TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */
+ g_defbytes (str, Count);
+ ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */
NextToken ();
} else {
ConsumeLCurly ();
- count = 0;
- while (curtok != TOK_RCURLY) {
+ Count = 0;
+ while (CurTok.Tok != TOK_RCURLY) {
ParseInit (T + DECODE_SIZE + 1);
- ++count;
- if (curtok != TOK_COMMA)
+ ++Count;
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
ConsumeRCurly ();
}
- if (sz == 0) {
- Encode (T + 1, count);
- } else if (count < sz) {
- g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
- } else if (count > sz) {
- Error (ERR_TOO_MANY_INITIALIZERS);
+ if (Size == 0) {
+ Encode (T + 1, Count);
+ } else if (Count < Size) {
+ g_zerobytes ((Size - Count) * SizeOf (T + DECODE_SIZE + 1));
+ } else if (Count > Size) {
+ Error ("Too many initializers");
}
break;
/* FALLTHROUGH */
default:
- Error (ERR_ILLEGAL_TYPE);
+ Error ("Illegal type");
break;
}