; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: Macros for importing functions in Linux
;
;  Target OS: Linux
;
;  Dependencies:
;
;  Notes:
;_________________________________________________________________________________________


include '_elf.inc'


macro interpreter [library]
{
 db library,0
}


macro __define_import_arguments [arg] {
common
  local ..start

  if arg eq VOID
    .__info.argtype=1
  else
    if arg eq NONE
      .__info.argtype = 0
    else
      virtual at ebp+8
        ..start:
forward
        if ~arg eq ...
          arg dd ?
        else
          label .more_arguments dword
        end if
common
        .__info.argsize = $ - ..start
      end virtual
      .__info.argtype = 2
    end if
  end if
}



macro __InitImportMacros {
common
  local libs, func

  libs equ 0
  func equ 0

  ; creates symbols list with needed libraries.
  macro import_proto library, [iname, arg, ename] \{
    \common
      \local str, cnt, use
      rept 1 i:libs+1 \\{
        libs equ i
        libs\\#i equ str:cnt:use:library
      \\}

    \forward
      \local fstr
      rept 1 i:func+1 \\{
        func equ i
        func\\#i equ fstr:cnt:iname:ename:arg
        iname\\#.@here = 1
      \\}
  \}

  macro __ImportAll \{
  \common
    \local strtab,strsz,symtab,rel,relsz,hash,tcnt, size1, size2

    tcnt = 0

    if defined options.ShowImported & options.ShowImported
      disp 3, 'Imported functions: ', <__imported_count, 10>, $09
    end if

    rept func i:1 \\{
      match fstr:cnt:iname:ename:arg, func\\#i \\\{
        if used iname
          tcnt = tcnt + 1
          if defined options.ShowImported & options.ShowImported
            display 3, 'Imported "', \\\`iname, '" function.', $0a
          end if
        end if
      \\\}
    \\}

    __imported_count = tcnt;

    size1 = 0

    if __imported_count>0
      segment dynamic readable
      rept libs i:1 \\{
        match str:cnt:use:library, libs\\#i \\\{
          cnt = 0
          if use > 0
            dd DT_NEEDED, str-strtab
          end if
        \\\}
      \\}

      dd DT_STRTAB, strtab
      dd DT_STRSZ, strsz
      dd DT_SYMTAB, symtab
      dd DT_SYMENT, sizeof.Elf32_Sym
      dd DT_REL, rel
      dd DT_RELSZ, relsz
      dd DT_RELENT, sizeof.Elf32_Rel
      dd DT_HASH, hash
      dd DT_NULL, 0

      size1 = $ - $$

      segment readable writeable
      symtab: Elf32_Sym

      rept func i:1 \\{
        match fstr:cnt:iname:ename:arg, func\\#i \\\{
          if used iname
            Elf32_Sym fstr-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0
            cnt = cnt + 1
          end if
        \\\}
      \\}

      rel:
      \local counter
      counter = 1

      rept func i:1 \\{
        match fstr:cnt:iname:ename:arg, func\\#i \\\{
          if used iname
            Elf32_Rel iname, counter, R_386_32
            counter = counter + 1
          end if
        \\\}
      \\}

      relsz = $-rel
      hash:
      dd 1, counter
      dd 0

      repeat counter
       if %=counter
        dd 0
       else
        dd %
       end if
      end repeat
      strtab db 0

      rept func i:1 \\{
        match fstr:cnt:iname:ename:arg, func\\#i \\\{
          if used iname
            fstr db ename, 0
          end if
        \\\}
      \\}

      rept libs i:1 \\{
        match str:cnt:use:library, libs\\#i \\\{
          use = cnt
          if use > 0
            str db library, 0
          end if
        \\\}
      \\}

      strsz = $-strtab

      rept func i:1 \\{
        match fstr:cnt:iname:ename:arg, func\\#i \\\{
          label iname dword
          if used iname
            dd 0
          end if
           __define_import_arguments arg
        \\\}
      \\}
    else
      size1 = $ - $$
    end if

    size2 = $ - $$

    DispSize 'ELF Import data1:', size1
    DispSize 'ELF Import data2:', size2
  \}
}


__InitImportMacros