/* */
/* */
/* */
-/* (C) 2000-2006 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "check.h"
#include "debugflag.h"
-#include "hashstr.h"
+#include "hashfunc.h"
#include "xmalloc.h"
/* cc65 */
unsigned Flags = Entry->Flags;
/* Ignore typedef entries */
- if ((Flags & SC_TYPEDEF) != SC_TYPEDEF) {
+ if (!SymIsTypeDef (Entry)) {
/* Check if the symbol is one with storage, and it if it was
* defined but not used.
*/
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
- if (SymIsDef (Entry) && !SymIsRef (Entry)) {
+ if (SymIsDef (Entry) && !SymIsRef (Entry) &&
+ !SymHasAttr (Entry, atUnused)) {
if (Flags & SC_PARAM) {
- Warning ("Parameter `%s' is never used", Entry->Name);
+ if (IS_Get (&WarnUnusedParam)) {
+ Warning ("Parameter `%s' is never used", Entry->Name);
+ }
} else {
- Warning ("`%s' is defined but never used", Entry->Name);
+ if (IS_Get (&WarnUnusedVar)) {
+ Warning ("`%s' is defined but never used", Entry->Name);
+ }
}
}
}
Error ("Undefined label: `%s'", Entry->Name);
} else if (!SymIsRef (Entry)) {
/* Defined but not used */
- Warning ("`%s' is defined but never used", Entry->Name);
+ if (IS_Get (&WarnUnusedLabel)) {
+ Warning ("`%s' is defined but never used", Entry->Name);
+ }
}
}
SymEntry* Field = 0;
/* The given type may actually be a pointer to struct */
- if (T->C == T_PTR) {
+ if (IsTypePtr (T)) {
++T;
}
/* Non-structs do not have any struct fields... */
if (IsClassStruct (T)) {
- const SymTable* Tab;
-
/* Get a pointer to the struct/union type */
const SymEntry* Struct = GetSymEntry (T);
CHECK (Struct != 0);
- /* Get the field symbol table from the struct entry.
- * Beware: The table may not exist.
+ /* Now search in the struct symbol table. Beware: The table may not
+ * exist.
*/
- Tab = Struct->V.S.SymTab;
-
- /* Now search in the struct symbol table */
- if (Tab) {
+ if (Struct->V.S.SymTab) {
Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
}
}
+SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width)
+/* Add a bit field to the local symbol table and return the symbol entry */
+{
+ /* Do we have an entry with this name already? */
+ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
+ if (Entry) {
+
+ /* We have a symbol with this name already */
+ Error ("Multiple definition for `%s'", Name);
+
+ } else {
+
+ /* Create a new entry */
+ Entry = NewSymEntry (Name, SC_BITFIELD);
+
+ /* Set the symbol attributes. Bit-fields are always of type unsigned */
+ Entry->Type = type_uint;
+ Entry->V.B.Offs = Offs;
+ Entry->V.B.BitOffs = BitOffs;
+ Entry->V.B.BitWidth = Width;
+
+ /* Add the entry to the symbol table */
+ AddSymEntry (SymTab, Entry);
+
+ }
+
+ /* Return the entry */
+ return Entry;
+}
+
+
+
SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
/* Add an constant symbol to the symbol table and return it */
{
TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
/* Types not identical: Conflicting types */
Error ("Conflicting types for `%s'", Name);
- return Entry;
+ return Entry;
} else {
/* Check if we have a size in the existing definition */
if (ESize == UNSPECIFIED) {
/* New type must be identical */
if (TypeCmp (EType, T) < TC_EQUAL) {
Error ("Conflicting types for `%s'", Name);
- return Entry;
+ return Entry;
}
/* In case of a function, use the new type descriptor, since it
* empty parameter list.
*/
if (IsFunc) {
- /* Get the function descriptor from the new type */
- FuncDesc* F = GetFuncDesc (T);
- /* Use this new function descriptor if it doesn't contain
+ /* Get the function descriptor from the new type */
+ FuncDesc* F = GetFuncDesc (T);
+ /* Use this new function descriptor if it doesn't contain
* an empty parameter list.
*/
if ((F->Flags & FD_EMPTY) == 0) {
+void EmitDebugInfo (void)
+/* Emit debug infos for the locals of the current scope */
+{
+ const char* Head;
+ const SymEntry* Sym;
+
+ /* Output info for locals if enabled */
+ if (DebugInfo) {
+ /* For cosmetic reasons in the output file, we will insert two tabs
+ * on global level and just one on local level.
+ */
+ if (LexicalLevel == LEX_LEVEL_GLOBAL) {
+ Head = "\t.dbg\t\tsym";
+ } else {
+ Head = "\t.dbg\tsym";
+ }
+ Sym = SymTab->SymHead;
+ while (Sym) {
+ if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
+ if (Sym->Flags & SC_AUTO) {
+ AddTextLine ("%s, \"%s\", \"00\", auto, %d",
+ Head, Sym->Name, Sym->V.Offs);
+ } else if (Sym->Flags & SC_REGISTER) {
+ AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
+ Head, Sym->Name, Sym->V.R.RegOffs);
+
+ } else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
+ AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
+ Head, Sym->Name,
+ (Sym->Flags & SC_EXTERN)? "extern" : "static",
+ Sym->AsmName);
+ }
+ }
+ Sym = Sym->NextSym;
+ }
+ }
+}
+
+
+