SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val) /* Add an constant symbol to the symbol table and return it */ { /* Enums must be inserted in the global symbol table */ SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { if ((Entry->Flags & SC_CONST) != SC_CONST) { Error ("Symbol `%s' is already different kind", Name); } else { Error ("Multiple definition for `%s'", Name); } return Entry; } /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Enum values are ints */ Entry->Type = TypeDup (T); /* Set the enum data */ Entry->V.ConstVal = Val; /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); /* Return the entry */ return Entry; }
CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E) /* If the code entry E does already have a label, return it. Otherwise * create a new label, attach it to E and return it. */ { CodeLabel* L; if (CE_HasLabel (E)) { /* Get the label from this entry */ L = CE_GetLabel (E, 0); } else { /* Get a new name */ const char* Name = LocalLabelName (GetLocalLabel ()); /* Generate the hash over the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; /* Create a new label */ L = CS_NewCodeLabel (S, Name, Hash); /* Attach this label to the code entry */ CE_AttachLabel (E, L); } /* Return the label */ return L; }
SymEntry* AddLabelSym (const char* Name, unsigned Flags) /* Add a goto label to the label table */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); if (Entry) { if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { /* Trying to define the label more than once */ Error ("Label `%s' is defined more than once", Name); } Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_LABEL | Flags); /* Set a new label number */ Entry->V.Label = GetLocalLabel (); /* Generate the assembler name of the label */ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label)); /* Add the entry to the label table */ AddSymEntry (LabelTab, Entry); } /* Return the entry */ return Entry; }
static void AddSymEntry (SymTable* T, SymEntry* S) /* Add a symbol to a symbol table */ { /* Get the hash value for the name */ unsigned Hash = HashStr (S->Name) % T->Size; /* Insert the symbol into the list of all symbols in this level */ if (T->SymTail) { T->SymTail->NextSym = S; } S->PrevSym = T->SymTail; T->SymTail = S; if (T->SymHead == 0) { /* First symbol */ T->SymHead = S; } ++T->SymCount; /* Insert the symbol into the hash chain */ S->NextHash = T->Tab[Hash]; T->Tab[Hash] = S; /* Tell the symbol in which table it is */ S->Owner = T; }
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* FindStructField (const Type* T, const char* Name) /* Find a struct field in the fields list */ { SymEntry* Field = 0; /* The given type may actually be a pointer to struct */ if (IsTypePtr (T)) { ++T; } /* Non-structs do not have any struct fields... */ if (IsClassStruct (T)) { /* Get a pointer to the struct/union type */ const SymEntry* Struct = GetSymEntry (T); CHECK (Struct != 0); /* Now search in the struct symbol table. Beware: The table may not ** exist. */ if (Struct->V.S.SymTab) { Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); } } return Field; }
void ExpInsert (const char* Name, unsigned Module) /* Insert an exported identifier and check if it's already in the list */ { HashEntry* L; /* Create a hash value for the given name */ unsigned HashVal = HashStr (Name) % HASHTAB_SIZE; /* Create a new hash entry */ HashEntry* H = NewHashEntry (Name, Module); /* Search through the list in that slot and print matching duplicates */ if (HashTab [HashVal] == 0) { /* The slot is empty */ HashTab [HashVal] = H; return; } L = HashTab [HashVal]; while (1) { if (strcmp (L->Name, Name) == 0) { /* Duplicate entry */ Warning ("External symbol `%s' in module `%s' is duplicated in " "module `%s'", Name, GetObjName (L->Module), GetObjName (Module)); } if (L->Next == 0) { break; } else { L = L->Next; } } L->Next = H; }
CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name) /* Add a code label for the next instruction to follow */ { /* Calculate the hash from the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; /* Try to find the code label if it does already exist */ CodeLabel* L = CS_FindLabel (S, Name, Hash); /* Did we find it? */ if (L) { /* We found it - be sure it does not already have an owner */ if (L->Owner) { Error ("ASM label `%s' is already defined", Name); return L; } } else { /* Not found - create a new one */ L = CS_NewCodeLabel (S, Name, Hash); } /* Safety. This call is quite costly, but safety is better */ if (CollIndex (&S->Labels, L) >= 0) { Error ("ASM label `%s' is already defined", Name); return L; } /* We do now have a valid label. Remember it for later */ CollAppend (&S->Labels, L); /* Return the label */ return L; }
void MakeZPSym (const char* Name) /* Mark the given symbol as zero page symbol */ { /* Get the symbol table entry */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); /* Mark the symbol as zeropage */ if (Entry) { Entry->Flags |= SC_ZEROPAGE; } else { Error ("Undefined symbol: `%s'", Name); } }
int ExpFind (const char* Name) /* Check for an identifier in the list. Return -1 if not found, otherwise * return the number of the module, that exports the identifer. */ { /* Get a pointer to the list with the symbols hash value */ HashEntry* L = HashTab [HashStr (Name) % HASHTAB_SIZE]; while (L) { /* Search through the list in that slot */ if (strcmp (L->Name, Name) == 0) { /* Entry found */ return L->Module; } L = L->Next; } /* Not found */ return -1; }
SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab) /* Add a struct/union entry and return it */ { SymEntry* Entry; /* Type must be struct or union */ PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); /* Do we have an entry with this name already? */ Entry = FindSymInTable (TagTab, Name, HashStr (Name)); if (Entry) { /* We do have an entry. This may be a forward, so check it. */ if ((Entry->Flags & SC_TYPEMASK) != Type) { /* Existing symbol is not a struct */ Error ("Symbol `%s' is already different kind", Name); } else if (Size > 0 && Entry->V.S.Size > 0) { /* Both structs are definitions. */ Error ("Multiple definition for `%s'", Name); } else { /* Define the struct size if it is given */ if (Size > 0) { Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; } } } else { /* Create a new entry */ Entry = NewSymEntry (Name, Type); /* Set the struct data */ Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; /* Add it to the current table */ AddSymEntry (TagTab, Entry); } /* Return the entry */ return Entry; }
SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) /* Add a local symbol 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, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); if ((Flags & SC_AUTO) == SC_AUTO) { Entry->V.Offs = Offs; } else if ((Flags & SC_REGISTER) == SC_REGISTER) { Entry->V.R.RegOffs = Offs; Entry->V.R.SaveOffs = StackPtr; } else if ((Flags & SC_EXTERN) == SC_EXTERN) { Entry->V.Label = Offs; SymSetAsmName (Entry); } else if ((Flags & SC_STATIC) == SC_STATIC) { /* Generate the assembler name from the label number */ Entry->V.Label = Offs; Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label)); } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { Entry->V.Offs = Offs; } else { Internal ("Invalid flags in AddLocalSym: %04X", Flags); } /* Add the entry to the symbol table */ AddSymEntry (SymTab, Entry); } /* Return the entry */ return Entry; }
static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name) /* Find the symbol with the given name in the table tree that starts with T */ { /* Get the hash over the name */ unsigned Hash = HashStr (Name); /* Check all symbol tables for the symbol */ while (Tab) { /* Try to find the symbol in this table */ SymEntry* E = FindSymInTable (Tab, Name, Hash); /* Bail out if we found it */ if (E != 0) { return E; } /* Repeat the search in the next higher lexical level */ Tab = Tab->PrevTab; } /* Not found */ return 0; }
unsigned int OpenUtility::CBlockStream::Hash(const OpenUtility::CBlockStream *str) { return(HashStr(str->GetStream())); }
SymEntry* FindLocalSym (const char* Name) /* Find the symbol with the given name in the current symbol table only */ { return FindSymInTable (SymTab, Name, HashStr (Name)); }
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; }
SymEntry* FindGlobalSym (const char* Name) /* Find the symbol with the given name in the global symbol table only */ { return FindSymInTable (SymTab0, Name, HashStr (Name)); }
static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) /* Parse an instruction nnd generate a code entry from it. If the line contains * errors, output an error message and return NULL. * For simplicity, we don't accept the broad range of input a "real" assembler * does. The instruction and the argument are expected to be separated by * white space, for example. */ { char Mnemo[IDENTSIZE+10]; const OPCDesc* OPC; am_t AM = 0; /* Initialize to keep gcc silent */ char Arg[IDENTSIZE+10]; char Reg; CodeEntry* E; CodeLabel* Label; /* Read the first token and skip white space after it */ L = SkipSpace (ReadToken (L, " \t:", Mnemo, sizeof (Mnemo))); /* Check if we have a label */ if (*L == ':') { /* Skip the colon and following white space */ L = SkipSpace (L+1); /* Add the label */ CS_AddLabel (S, Mnemo); /* If we have reached end of line, bail out, otherwise a mnemonic * may follow. */ if (*L == '\0') { return 0; } L = SkipSpace (ReadToken (L, " \t", Mnemo, sizeof (Mnemo))); } /* Try to find the opcode description for the mnemonic */ OPC = FindOP65 (Mnemo); /* If we didn't find the opcode, print an error and bail out */ if (OPC == 0) { Error ("ASM code error: %s is not a valid mnemonic", Mnemo); return 0; } /* Get the addressing mode */ Arg[0] = '\0'; switch (*L) { case '\0': /* Implicit or accu */ if (OPC->Info & OF_NOIMP) { AM = AM65_ACC; } else { AM = AM65_IMP; } break; case '#': /* Immidiate */ StrCopy (Arg, sizeof (Arg), L+1); AM = AM65_IMM; break; case '(': /* Indirect */ L = ReadToken (L+1, ",)", Arg, sizeof (Arg)); /* Check for errors */ if (*L == '\0') { Error ("ASM code error: syntax error"); return 0; } /* Check the different indirect modes */ if (*L == ',') { /* Expect zp x indirect */ L = SkipSpace (L+1); if (toupper (*L) != 'X') { Error ("ASM code error: `X' expected"); return 0; } L = SkipSpace (L+1); if (*L != ')') { Error ("ASM code error: `)' expected"); return 0; } L = SkipSpace (L+1); if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } AM = AM65_ZPX_IND; } else if (*L == ')') { /* zp indirect or zp indirect, y */ L = SkipSpace (L+1); if (*L == ',') { L = SkipSpace (L+1); if (toupper (*L) != 'Y') { Error ("ASM code error: `Y' expected"); return 0; } L = SkipSpace (L+1); if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } AM = AM65_ZP_INDY; } else if (*L == '\0') { AM = AM65_ZP_IND; } else { Error ("ASM code error: syntax error"); return 0; } } break; case 'a': case 'A': /* Accumulator? */ if (L[1] == '\0') { AM = AM65_ACC; break; } /* FALLTHROUGH */ default: /* Absolute, maybe indexed */ L = ReadToken (L, ",", Arg, sizeof (Arg)); if (*L == '\0') { /* Absolute, zeropage or branch */ if ((OPC->Info & OF_BRA) != 0) { /* Branch */ AM = AM65_BRA; } else if (GetZPInfo(Arg) != 0) { AM = AM65_ZP; } else { /* Check for subroutine call to local label */ if ((OPC->Info & OF_CALL) && IsLocalLabelName (Arg)) { Error ("ASM code error: " "Cannot use local label `%s' in subroutine call", Arg); } AM = AM65_ABS; } } else if (*L == ',') { /* Indexed */ L = SkipSpace (L+1); if (*L == '\0') { Error ("ASM code error: syntax error"); return 0; } else { Reg = toupper (*L); L = SkipSpace (L+1); if (Reg == 'X') { if (GetZPInfo(Arg) != 0) { AM = AM65_ZPX; } else { AM = AM65_ABSX; } } else if (Reg == 'Y') { AM = AM65_ABSY; } else { Error ("ASM code error: syntax error"); return 0; } if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } } } break; } /* If the instruction is a branch, check for the label and generate it * if it does not exist. This may lead to unused labels (if the label * is actually an external one) which are removed by the CS_MergeLabels * function later. */ Label = 0; if (AM == AM65_BRA) { /* Generate the hash over the label, then search for the label */ unsigned Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE; Label = CS_FindLabel (S, Arg, Hash); /* If we don't have the label, it's a forward ref - create it */ if (Label == 0) { /* Generate a new label */ Label = CS_NewCodeLabel (S, Arg, Hash); } } /* We do now have the addressing mode in AM. Allocate a new CodeEntry * structure and initialize it. */ E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI); /* Return the new code entry */ return E; }