void SetElementCount (Type* T, long Count) /* Set the element count of the array specified in T (which must be of ** array type). */ { CHECK (IsTypeArray (T)); T->A.L = Count; }
long GetElementCount (const Type* T) /* Get the element count of the array specified in T (which must be of ** array type). */ { CHECK (IsTypeArray (T)); return T->A.L; }
Type* GetBaseElementType (Type* T) /* Return the base element type of a given type. If T is not an array, this ** will return. Otherwise it will return the base element type, which means ** the element type that is not an array. */ { while (IsTypeArray (T)) { ++T; } return T; }
Type* PtrConversion (Type* T) /* If the type is a function, convert it to pointer to function. If the ** expression is an array, convert it to pointer to first element. Otherwise ** return T. */ { if (IsTypeFunc (T)) { return PointerTo (T); } else if (IsTypeArray (T)) { return ArrayToPtr (T); } else { return T; } }
static long ArrayElementCount (const ArgDesc* Arg) /* Check if the type of the given argument is an array. If so, and if the * element count is known, return it. In all other cases, return UNSPECIFIED. */ { long Count; if (IsTypeArray (Arg->Type)) { Count = GetElementCount (Arg->Type); if (Count == FLEXIBLE) { /* Treat as unknown */ Count = UNSPECIFIED; } } else { Count = UNSPECIFIED; } return Count; }
Type* GetElementType (Type* T) /* Return the element type of the given array type. */ { CHECK (IsTypeArray (T)); return T + 1; }
int TypeHasAttr (const Type* T) /* Return true if the given type has attribute data */ { return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); }
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { /* There is some special handling for functions, so check if it is one */ int IsFunc = IsTypeFunc (T); /* Functions must be inserted in the global symbol table */ SymTable* Tab = IsFunc? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { Type* EType; /* We have a symbol with this name already */ if (Entry->Flags & SC_TYPE) { Error ("Multiple definition for `%s'", Name); return Entry; } /* Get the type string of the existing symbol */ EType = Entry->Type; /* If we are handling arrays, the old entry or the new entry may be an ** incomplete declaration. Accept this, and if the exsting entry is ** incomplete, complete it. */ if (IsTypeArray (T) && IsTypeArray (EType)) { /* Get the array sizes */ long Size = GetElementCount (T); long ESize = GetElementCount (EType); if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || TypeCmp (T + 1, EType + 1) < TC_EQUAL) { /* Types not identical: Conflicting types */ Error ("Conflicting types for `%s'", Name); return Entry; } else { /* Check if we have a size in the existing definition */ if (ESize == UNSPECIFIED) { /* Existing, size not given, use size from new def */ SetElementCount (EType, Size); } } } else { /* New type must be identical */ if (TypeCmp (EType, T) < TC_EQUAL) { Error ("Conflicting types for `%s'", Name); return Entry; } /* In case of a function, use the new type descriptor, since it ** contains pointers to the new symbol tables that are needed if ** an actual function definition follows. Be sure not to use the ** new descriptor if it contains a function declaration with an ** 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 ** an empty parameter list. */ if ((F->Flags & FD_EMPTY) == 0) { Entry->V.F.Func = F; SetFuncDesc (EType, F); } } } /* Add the new flags */ Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); /* If this is a function, set the function descriptor and clear ** additional fields. */ if (IsFunc) { Entry->V.F.Func = GetFuncDesc (Entry->Type); Entry->V.F.Seg = 0; } /* Add the assembler name of the symbol */ SymSetAsmName (Entry); /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); } /* Return the entry */ return Entry; }