#include "common.h"
#include "newalloc.h"
+/* noun strings */
+char *nounName(sym_link *sl) {
+ switch (SPEC_NOUN(sl))
+ {
+ case V_INT: {
+ if (SPEC_LONG(sl)) return "long";
+ if (SPEC_SHORT(sl)) return "short";
+ return "int";
+ }
+ case V_FLOAT: return "float";
+ case V_CHAR: return "char";
+ case V_VOID: return "void";
+ case V_STRUCT: return "struct";
+ case V_LABEL: return "label";
+ case V_BIT: return "bit";
+ case V_SBIT: return "sbit";
+ case V_DOUBLE: return "double";
+ }
+ return "unknown";
+};
+
bucket *SymbolTab[256]; /* the symbol table */
bucket *StructTab[256]; /* the structure table */
bucket *TypedefTab[256]; /* the typedef table */
int i; /* index into the hash Table */
bucket *bp; /* temp bucket * */
+ checkTypeSanity(((symbol *)sym)->etype, sname);
+
/* the symbols are always added at the head of the list */
i = hashKey (sname);
/* get a free entry */
return;
}
+/*------------------------------------------------------------------
+ checkTypeSanity: prevent the user from doing e.g.:
+ unsigned float uf;
+ ------------------------------------------------------------------*/
+void checkTypeSanity(sym_link *dest, char *name) {
+ char *noun;
+
+ if (!dest) {
+ //printf ("sanity check skipped for %s\n", name);
+ return;
+ }
+
+ noun=nounName(dest);
+
+ //printf ("checking sanity for %s\n", name);
+
+ if ((SPEC_NOUN(dest)==V_CHAR ||
+ SPEC_NOUN(dest)==V_FLOAT ||
+ SPEC_NOUN(dest)==V_DOUBLE ||
+ SPEC_NOUN(dest)==V_VOID) &&
+ (SPEC_SHORT(dest) || SPEC_LONG(dest))) {
+ // long or short for char float double or void
+ werror (E_LONG_OR_SHORT_INVALID, noun, name);
+ }
+ if ((SPEC_NOUN(dest)==V_FLOAT ||
+ SPEC_NOUN(dest)==V_DOUBLE ||
+ SPEC_NOUN(dest)==V_VOID) &&
+ (SPEC_SIGNED(dest) || SPEC_USIGN(dest))) {
+ // signed or unsigned for float double or void
+ werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name);
+ }
+ if (SPEC_SIGNED(dest) && SPEC_USIGN(dest)) {
+ // signed AND unsigned
+ werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
+ }
+ if (SPEC_SHORT(dest) && SPEC_LONG(dest)) {
+ // short AND long
+ werror (E_LONG_AND_SHORT_INVALID, noun, name);
+ }
+
+}
+
/*------------------------------------------------------------------*/
-/* mergeSpec - merges two specifiers and returns the new one */
+/* mergeSpec - merges two specifiers and returns the new one */
/*------------------------------------------------------------------*/
sym_link *
mergeSpec (sym_link * dest, sym_link * src)
{
+
+ /* we shouldn't redeclare the type */
+ if ((SPEC_NOUN (dest) && SPEC_NOUN (src)) &&
+ (SPEC_NOUN(dest) != SPEC_NOUN(src))) {
+ werror(E_TWO_OR_MORE_DATA_TYPES, yylval.yychar);
+ }
+
/* if noun different then src overrides */
if (SPEC_NOUN (dest) != SPEC_NOUN (src) && !SPEC_NOUN (dest))
SPEC_NOUN (dest) = SPEC_NOUN (src);
SPEC_LONG (dest) |= SPEC_LONG (src);
SPEC_SHORT (dest) |= SPEC_SHORT (src);
SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ SPEC_SIGNED (dest) |= SPEC_SIGNED (src);
SPEC_STAT (dest) |= SPEC_STAT (src);
SPEC_EXTR (dest) |= SPEC_EXTR (src);
SPEC_ABSA (dest) |= SPEC_ABSA (src);
}
/*------------------------------------------------------------------*/
-/* newCharLink() - creates an int type */
+/* newCharLink() - creates an char type */
/*------------------------------------------------------------------*/
sym_link *
newCharLink ()
symbol *sym = symHead;
symbol *csym = NULL;
+
for (; sym != NULL; sym = sym->next)
{
changePointer(sym);
+
/* if already exists in the symbol table then check if
the previous was an extern definition if yes then
then check if the type match, if the types match then
{
/* previous definition extern ? */
- if (IS_EXTERN (csym->etype))
+ if (1 || IS_EXTERN (csym->etype))
{
/* do types match ? */
if (checkType (csym->type, sym->type) != 1)
werror (W_EXTERN_MISMATCH, csym->name);
}
}
-
addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
}
}
if (checkType (csym->type, sym->type) <= 0)
{
werror (E_PREV_DEF_CONFLICT, csym->name, "type");
- werror (E_CONTINUE, "previous defintion type ");
+ werror (E_CONTINUE, "previous definition type ");
printTypeChain (csym->type, stderr);
fprintf (stderr, "\n");
werror (E_CONTINUE, "current definition type ");
case V_INT:
if (IS_LONG (type))
fprintf (of, "long ");
- else if (IS_SHORT (type))
+ if (IS_SHORT (type))
fprintf (of, "short ");
- else
- fprintf (of, "int ");
+ fprintf (of, "int ");
break;
case V_CHAR:
fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
break;
+ case V_DOUBLE:
+ fprintf (of, "double ");
+ break;
+
default:
+ fprintf (of, "unknown type ");
break;
}
}