+ /* First, remove all labels from the label symbol table that don't have an
+ * owner (this means that they are actually external labels but we didn't
+ * know that previously since they may have also been forward references).
+ */
+ for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
+
+ /* Get the first label in this hash chain */
+ CodeLabel** L = &S->LabelHash[I];
+ while (*L) {
+ if ((*L)->Owner == 0) {
+
+ /* The label does not have an owner, remove it from the chain */
+ CodeLabel* X = *L;
+ *L = X->Next;
+
+ /* Cleanup any entries jumping to this label */
+ for (J = 0; J < CL_GetRefCount (X); ++J) {
+ /* Get the entry referencing this label */
+ CodeEntry* E = CL_GetRef (X, J);
+ /* And remove the reference */
+ E->JumpTo = 0;
+ }
+
+ /* Print some debugging output */
+ if (Debug) {
+ printf ("Removing unused global label `%s'", X->Name);
+ }
+
+ /* And free the label */
+ FreeCodeLabel (X);
+ } else {
+ /* Label is owned, point to next code label pointer */
+ L = &((*L)->Next);
+ }
+ }
+ }
+
+ /* Walk over all code entries */
+ for (I = 0; I < CS_GetEntryCount (S); ++I) {
+
+ CodeLabel* RefLab;
+ unsigned J;
+
+ /* Get a pointer to the next entry */
+ CodeEntry* E = CS_GetEntry (S, I);
+
+ /* If this entry has zero labels, continue with the next one */
+ unsigned LabelCount = CE_GetLabelCount (E);
+ if (LabelCount == 0) {
+ continue;
+ }
+
+ /* We have at least one label. Use the first one as reference label. */
+ RefLab = CE_GetLabel (E, 0);
+
+ /* Walk through the remaining labels and change references to these
+ * labels to a reference to the one and only label. Delete the labels
+ * that are no longer used. To increase performance, walk backwards
+ * through the list.
+ */
+ for (J = LabelCount-1; J >= 1; --J) {
+
+ /* Get the next label */
+ CodeLabel* L = CE_GetLabel (E, J);
+
+ /* Move all references from this label to the reference label */
+ CL_MoveRefs (L, RefLab);
+
+ /* Remove the label completely. */
+ CS_DelLabel (S, L);
+ }
+
+ /* The reference label is the only remaining label. Check if there
+ * are any references to this label, and delete it if this is not
+ * the case.
+ */
+ if (CollCount (&RefLab->JumpFrom) == 0) {
+ /* Delete the label */
+ CS_DelLabel (S, RefLab);
+ }
+ }
+}
+
+
+
+void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New)
+/* Move all labels from Old to New. The routine will move the labels itself
+ * if New does not have any labels, and move references if there is at least
+ * a label for new. If references are moved, the old label is deleted
+ * afterwards.
+ */
+{
+ /* Get the number of labels to move */
+ unsigned OldLabelCount = CE_GetLabelCount (Old);
+
+ /* Does the new entry have itself a label? */
+ if (CE_HasLabel (New)) {
+
+ /* The new entry does already have a label - move references */
+ CodeLabel* NewLabel = CE_GetLabel (New, 0);
+ while (OldLabelCount--) {
+
+ /* Get the next label */
+ CodeLabel* OldLabel = CE_GetLabel (Old, OldLabelCount);
+
+ /* Move references */
+ CL_MoveRefs (OldLabel, NewLabel);
+
+ /* Delete the label */
+ CS_DelLabel (S, OldLabel);
+
+ }
+
+ } else {
+
+ /* The new entry does not have a label, just move them */
+ while (OldLabelCount--) {
+
+ /* Move the label to the new entry */
+ CE_MoveLabel (CE_GetLabel (Old, OldLabelCount), New);
+
+ }
+
+ }
+}
+
+
+
+void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E)
+/* Remove the reference between E and the label it jumps to. The reference
+ * will be removed on both sides and E->JumpTo will be 0 after that. If
+ * the reference was the only one for the label, the label will get
+ * deleted.
+ */
+{
+ /* Get a pointer to the label and make sure it exists */
+ CodeLabel* L = E->JumpTo;
+ CHECK (L != 0);
+
+ /* Delete the entry from the label */
+ CollDeleteItem (&L->JumpFrom, E);
+
+ /* The entry jumps no longer to L */
+ E->JumpTo = 0;
+
+ /* If there are no more references, delete the label */
+ if (CollCount (&L->JumpFrom) == 0) {
+ CS_DelLabel (S, L);
+ }
+}
+
+
+
+void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
+/* Change the reference of E to L instead of the current one. If this
+ * was the only reference to the old label, the old label will get
+ * deleted.
+ */
+{
+ /* Get the old label */
+ CodeLabel* OldLabel = E->JumpTo;