; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
    include \masm32\include\masm32rt.inc
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

comment * -----------------------------------------------------
                        Build this  utility  with
                       "CONSOLE ASSEMBLE AND LINK"

        This utility is designed to use a list of EXPORT names
        from a DLL written using the C calling convention for
        such exports. You would normaly use DUMPBIN or DUMPPE
        to create such a list.

        The file containing the BARE list of EXPORT names
        should have the same bare name as the DLL that contains
        the exports as the internal and external names for
        the library and the include file are based off the name
        of the file that has the list of exported names in it.

        This file was originally designed to create an EXPORT
        library for the MSVCRT.DLL file and this is reflected
        by prepending the characters "crt_" to the EXPORT
        function names as they can be called from MASM in the
        include file.
        ----------------------------------------------------- *

    linecount  PROTO :DWORD
    strip_ext  PROTO :DWORD

    .code

start:
   
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

    call main

    exit

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

main proc

    LOCAL hMem  :DWORD                  ; memory handle
    LOCAL lcnt  :DWORD                  ; line count
    LOCAL spos  :DWORD                  ; linein$ location pointer
    LOCAL hFile :DWORD                  ; file handle
    LOCAL pbuf  :DWORD                  ; buffer pointer
    LOCAL pprn  :DWORD                  ; file print pointer
    LOCAL pbrn  :DWORD                  ; pointer to buffer for bare file name
    LOCAL buffer[128]:BYTE              ; 128 byte buffer
    LOCAL prnbuf[128]:BYTE              ; append buffer for file output
    LOCAL bname [128]:BYTE              ; buffer for bare file name with extension stripped

    mov pbuf, ptr$(buffer)              ; cast buffer to a pointer

    invoke GetCL,1,pbuf                 ; get 1st arg on command line
    .if rv(exist,pbuf) == 0
      print "command line file not found",13,10,13,10
      print "makecimp.exe (c) The MASM32 Project 1998-2005",13,10
      print "SYNTAX : makecimp filename.ext",13,10
      print "         filename.ext MUST be a list of the names",13,10
      print "         EXPORTED from a C calling convention DLL",13,10,13,10
      print "NOTE   : The name of the file used on the command line",13,10
      print "         controls the name of the LIB and INC file",13,10
      print "         generated by makecimp.exe",13,10
      ret
    .endif

    mov pbrn, ptr$(bname)
    cst pbrn, pbuf                      ; copy file name to bare name buffer
    invoke strip_ext,pbrn               ; strip the extension from file name

    mov hMem, InputFile(pbuf)           ; load file into memory
    mov lcnt, rv(linecount,hMem)        ; count the number of lines in text file
    add lcnt, 1                         ; add 1 for last line

  ; **************************
  ; create the DEFINITION file
  ; **************************

    push esi                            ; preserve ESI
    mov esi, lcnt                       ; use ESI for counter
    mov spos, 0                         ; zero file offset variable

    mov pprn, ptr$(prnbuf)              ; set print buffer to zero length
    mov hFile, fcreate(cat$(pprn,pbrn,".def"))

    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"LIBRARY ",pbrn,chr$(13,10))
  lp1:
    mov spos, linein$(hMem,pbuf,spos)   ; read each line into a buffer
    cmp tstline$(pbuf), 0               ; don't print empty line
    je @F
    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"EXPORTS ",pbuf)
  @@:
    sub esi, 1
    jnz lp1

    fclose hFile

  ; ***********************
  ; create the INCLUDE file
  ; ***********************

    mov esi, lcnt                       ; use ESI for counter
    mov spos, 0                         ; zero file offset variable

    mov pprn, ptr$(prnbuf)              ; set print buffer to zero length
    mov hFile, fcreate(cat$(pprn,pbrn,".inc"))

    fprint hFile,"  ; ------------------------------------------"
    mov pprn, ptr$(prnbuf)              ; set print buffer to zero length
    fprint hFile,cat$(pprn,"  ; prototypes for EXPORT ",pbrn," functions")

    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"  ; ------------------------------------------",chr$(13,10))

    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"    c_",pbrn," typedef PROTO C :VARARG",chr$(13,10))
  lp2:
    mov spos, linein$(hMem,pbuf,spos)   ; read each line into a buffer
    cmp tstline$(pbuf), 0               ; don't print empty line
    je @F
    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"    externdef _imp__",pbuf,":PTR c_",pbrn)
    mov pprn, ptr$(prnbuf)
    fprint hFile,cat$(pprn,"    crt_",pbuf," equ ",chr$(60),"_imp__",pbuf,chr$(62),chr$(13,10))
  @@:
    sub esi, 1
    jnz lp2

    fclose hFile                        ; close the file handle
    free hMem                           ; deallocate the file memory
    pop esi

  ; *******************************************
  ; build the library with the Microsoft linker
  ; *******************************************

    mov pprn, ptr$(prnbuf)
    fn shell_ex,cat$(pprn,"\masm32\bin\link -lib /machine:ix86 /def:",pbrn,".def"), \
                HIGH_PRIORITY_CLASS
    ret

main endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

align 4

linecount proc txt:DWORD

  ; ---------------------------------------------
  ; get line count of text by counting line feeds
  ; ---------------------------------------------
    mov eax, -1
    mov ecx, txt
    sub ecx, 1

  pre:
    add eax, 1                              ; add 1 to return value if LF found
  @@:
    add ecx, 1
    cmp BYTE PTR [ecx], 0                   ; test for zero terminator
    je lbl0
    cmp BYTE PTR [ecx], 10                  ; test line feed
    je pre
    jmp @B

  lbl0:

    ret

linecount endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

align 4

strip_ext proc txt:DWORD

    mov eax, txt
    sub eax, 1

  @@:
    add eax, 1
    cmp BYTE PTR [eax], "."
    jne nxt
    mov BYTE PTR [eax], 0
    jmp seout
  nxt:
    cmp BYTE PTR [eax], 0
    jne @B

  seout:

    ret

strip_ext endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

end start
