%if 0

Extensions for lDebug data relocation macros

Copyright (C) 2008-2024 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif

%ifndef ELDDATA_MAC
%define ELDDATA_MAC 1

%include "lmacros3.mac"
%include "nasmhash.mac"
%include "eldcheck.mac"


%assign ELDLINKER 0

%define INTERNAL_CODE_TO_CODE_RELOCATIONS ""
%define INTERNAL_CODE_TO_DATA_RELOCATIONS ""
%define INTERNAL_DATA_TO_CODE_RELOCATIONS ""
%define INTERNAL_DATA_TO_DATA_RELOCATIONS ""
%define INTERNAL_LINKER_CODE_TO_CODE_RELOCATIONS ""
%define INTERNAL_LINKER_CODE_TO_DATA_RELOCATIONS ""
%define INTERNAL_LINKER_DATA_TO_CODE_RELOCATIONS ""
%define INTERNAL_LINKER_DATA_TO_DATA_RELOCATIONS ""
%assign ELDDATA_OPTIONAL_STATUS 0		; not any seen yet
%assign ELDDATA_PMREQUIRED_STATUS 0		; not any seen yet
%assign ELDDATA_NEXT_STATUS 0			; not any seen yet
%assign ELDDATA_NEXT_ENTRY -1
%assign ELDDATA_NEXT_SECTION -1
%assign ELDDATA_NEXT_OTHER -1

	%imacro internalcoderelocation 0-1.nolist -2
%assign %%entry $ + _CURRENT_SECTION %+ FIXUP + %1
%if ELDLINKER
 %ifidni _CURRENT_SECTION_TYPE, DATA
  %xdefine INTERNAL_LINKER_DATA_TO_CODE_RELOCATIONS INTERNAL_LINKER_DATA_TO_CODE_RELOCATIONS, %%entry
 %else
  %xdefine INTERNAL_LINKER_CODE_TO_CODE_RELOCATIONS INTERNAL_LINKER_CODE_TO_CODE_RELOCATIONS, %%entry
 %endif
%else
 %ifidni _CURRENT_SECTION_TYPE, DATA
  %xdefine INTERNAL_DATA_TO_CODE_RELOCATIONS INTERNAL_DATA_TO_CODE_RELOCATIONS, %%entry
 %else
  %xdefine INTERNAL_CODE_TO_CODE_RELOCATIONS INTERNAL_CODE_TO_CODE_RELOCATIONS, %%entry
 %endif
%endif
	eldstrictcheck
	%endmacro

	%imacro internaldatarelocation 0-1.nolist -2
%assign %%entry $ + _CURRENT_SECTION %+ FIXUP + %1
%if ELDLINKER
 %ifidni _CURRENT_SECTION_TYPE, DATA
  %xdefine INTERNAL_LINKER_DATA_TO_DATA_RELOCATIONS INTERNAL_LINKER_DATA_TO_DATA_RELOCATIONS, %%entry
 %else
  %xdefine INTERNAL_LINKER_CODE_TO_DATA_RELOCATIONS INTERNAL_LINKER_CODE_TO_DATA_RELOCATIONS, %%entry
 %endif
%else
 %ifidni _CURRENT_SECTION_TYPE, DATA
  %xdefine INTERNAL_DATA_TO_DATA_RELOCATIONS INTERNAL_DATA_TO_DATA_RELOCATIONS, %%entry
 %else
  %xdefine INTERNAL_CODE_TO_DATA_RELOCATIONS INTERNAL_CODE_TO_DATA_RELOCATIONS, %%entry
 %endif
%endif
	eldstrictcheck
	%endmacro

; dw INTERNAL_LINKER_CODE_TO_CODE_RELOCATIONS, 0
; dw INTERNAL_LINKER_CODE_TO_DATA_RELOCATIONS, 0
; dw INTERNAL_LINKER_DATA_TO_CODE_RELOCATIONS, -1
; dw INTERNAL_LINKER_DATA_TO_DATA_RELOCATIONS, -1
; dw INTERNAL_CODE_TO_CODE_RELOCATIONS, 0
; dw INTERNAL_CODE_TO_DATA_RELOCATIONS, 0
; dw INTERNAL_DATA_TO_CODE_RELOCATIONS, -1
; dw INTERNAL_DATA_TO_DATA_RELOCATIONS, -1


%define LINK_DATA_RELOCATIONS ""
%define LINK_LINKER_DATA_RELOCATIONS ""
%define LINK_DATA_NAMES db ""
%define LINK_DATA_DETECTION none, none

%define LINK_OTHER_DATA_RELOCATIONS ""
%define LINK_OTHER_LINKER_DATA_RELOCATIONS ""
%define LINK_OTHER_DATA_NAMES db ""
%define LINK_OTHER_DATA_DETECTION none, none

%ifndef ELDOTHER
 %assign ELDOTHER 0
%endif
%assign ELDOTHERLINK 0

	%imacro otherlinkdatarelocation 1-3.nolist -2, required
%if ELDOTHER
 %assign ELDOTHERLINK 1
%endif
	linkdatarelocation %1, %2, %3
%assign ELDOTHERLINK 0
	%endmacro

	%imacro linkdatarelocation 1-4.nolist -2, required, single
%assign %%entry $ + _CURRENT_SECTION %+ FIXUP + %2
%ifidni %3, required
 %assign %%optional 0
%elifidni %3, optional
 %assign %%optional 100h
 %if ELDDATA_OPTIONAL_STATUS == 0
  %assign ELDDATA_OPTIONAL_STATUS 1
 %elif ELDDATA_OPTIONAL_STATUS == 1
 %else
  %error Optional data link not allowed here
 %endif
%elifidni %3, PM required
 %assign %%optional 300h
 %assign ELDDATA_PMREQUIRED_STATUS 1
 %if ELDDATA_OPTIONAL_STATUS == 0
  %assign ELDDATA_OPTIONAL_STATUS 1
 %elif ELDDATA_OPTIONAL_STATUS == 1
 %else
  %error Optional data link not allowed here
 %endif
%else
 %fatal Unknown optional keyword
%endif
%ifidni _CURRENT_SECTION_TYPE, DATA
 %assign %%DATASECTION 1
%else
 %assign %%DATASECTION 0
%endif
%ifidni %4, single
 %if ELDDATA_NEXT_STATUS == 1		; after next ?
  %error Unexpected single data link after next data link
 %elif ELDDATA_NEXT_STATUS == 2		; after last ?
  %assign ELDDATA_NEXT_STATUS 3		; note single with next/last present
 %endif
 %assign %%next 0
%elifidni %4, next
 %if ELDDATA_NEXT_STATUS == 0		; no next/last yet ?
  %assign ELDDATA_NEXT_STATUS 1		; in next
 %elif ELDDATA_NEXT_STATUS == 2		; after last ?
  %assign ELDDATA_NEXT_STATUS 1		; in next
 %elif ELDDATA_NEXT_STATUS == 3		; after single ?
  %assign ELDDATA_NEXT_STATUS 1		; in next
 %elif ELDDATA_NEXT_STATUS == 1		; repeated next ?
  %if ELDDATA_NEXT_ENTRY != %%entry \
	|| ELDDATA_NEXT_SECTION != %%DATASECTION \
	|| ELDDATA_NEXT_OTHER != ELDOTHERLINK
   %error Unexpected next data link
  %endif
 %else
  %error Next data link not allowed here
 %endif
 %ifn %%optional
  %error Next data link only valid as optional or PM required
 %endif
 %assign %%next 400h
 %assign ELDDATA_NEXT_ENTRY %%entry
 %assign ELDDATA_NEXT_SECTION %%DATASECTION
 %assign ELDDATA_NEXT_OTHER ELDOTHERLINK
%elifidni %4, last
 %if ELDDATA_NEXT_STATUS == 0		; no next/last yet ?
  %error Next last data link not allowed here
 %elif ELDDATA_NEXT_STATUS == 2		; after last ?
  %error Next last data link not allowed here
 %elif ELDDATA_NEXT_STATUS == 3		; after single ?
  %error Next last data link not allowed here
 %elif ELDDATA_NEXT_STATUS == 1		; after next ?
  %if ELDDATA_NEXT_ENTRY != %%entry \
	|| ELDDATA_NEXT_SECTION != %%DATASECTION \
	|| ELDDATA_NEXT_OTHER != ELDOTHERLINK
   %error Unexpected next data link
  %endif
  %assign ELDDATA_NEXT_STATUS 2		; note now after last
 %else
  %error Next data link not allowed here
 %endif
 %assign %%next 800h
 %assign ELDDATA_NEXT_ENTRY -1
 %assign ELDDATA_NEXT_SECTION -1
%else
 %fatal Unknown next keyword
%endif
	%if ELDOTHERLINK
%if ELDLINKER
 %xdefine LINK_OTHER_LINKER_DATA_RELOCATIONS LINK_OTHER_LINKER_DATA_RELOCATIONS, 1 + %%DATASECTION + %%optional + %%next, %%entry, %%name
%else
 %xdefine LINK_OTHER_DATA_RELOCATIONS LINK_OTHER_DATA_RELOCATIONS, 1 + %%DATASECTION + %%optional + %%next, %%entry, %%name
%endif
	%else
%if ELDLINKER
 %xdefine LINK_LINKER_DATA_RELOCATIONS LINK_LINKER_DATA_RELOCATIONS, 1 + %%DATASECTION + %%optional + %%next, %%entry, %%name
%else
 %xdefine LINK_DATA_RELOCATIONS LINK_DATA_RELOCATIONS, 1 + %%DATASECTION + %%optional + %%next, %%entry, %%name
%endif
	%endif
%defstr %%string %1
%strlen %%length %%string
%if %%length > 64
	; Could be increased, but mustn't exceed 127 bytes
	;  because flag 80h is used to mark optional links
	;  that failed to be matched.
 %error Too long link name: %1
%endif
%define LINK_DATA_CHECK %1
	%if ELDOTHERLINK
	linkdata_detect LINK_OTHER_DATA_DETECTION
%if LINK_DATA_NEW
 %xdefine LINK_OTHER_DATA_DETECTION LINK_OTHER_DATA_DETECTION, %1, %%name
	hashdef HASH, %%string
 %xdefine LINK_OTHER_DATA_NAMES \
	LINK_OTHER_DATA_NAMES, %%name:, dw _HASH, {counted %%string}
%else
 %%name equ LINK_DATA_DUPLICATE
%endif
	%else
	linkdata_detect LINK_DATA_DETECTION
%if LINK_DATA_NEW
 %xdefine LINK_DATA_DETECTION LINK_DATA_DETECTION, %1, %%name
	hashdef HASH, %%string
 %xdefine LINK_DATA_NAMES \
	LINK_DATA_NAMES, %%name:, dw _HASH, {counted %%string}
%else
 %%name equ LINK_DATA_DUPLICATE
%endif
	%endif
	eldstrictcheck
	%endmacro

	%imacro linkdata_detect 2-*.nolist
%assign LINK_DATA_NEW 1
%rep (%0 - 2) / 2
 %rotate 2
 %ifidni %1, LINK_DATA_CHECK
  %assign LINK_DATA_NEW 0
  %xdefine LINK_DATA_DUPLICATE %2
  %exitrep
 %endif
%endrep
	%endmacro

	%imacro link_data_dump_names 1-*.nolist
%rep %0
	%1
 %rotate 1
%endrep
	%endmacro

; dw LINK_LINKER_DATA_RELOCATIONS, 0, 0
; dw LINK_DATA_RELOCATIONS, 0, 0
; link_data_dump_names ELDCALL_CODE_NAMES

%endif
