Page 1 of 1

File format of the user libs ?

Posted: Sat May 05, 2012 2:27 pm
by Zebuddi123
Hi to all


could someone please advice me as to the fileformat of the userlibs also does the pbcompiler read in the procedures from the userlibs etc (i presume so as with restarting the compiler after installing new libs) have looked through japbe source nothing there only ref to purelibraries are in checkcompilerflags() and [GetTailBiteFile1() GetTailBiteFile2() but these dont seem to be called anywhere only defined)

how would i go about reading in from the userlibs the procedure names etc (where can i find info on the header offsets etc and how to read it like the compiler does)

i have hacked some code that does the job but not for all files (and it is a hack as i have had to look through the user libs for identifiers for which parts to pull (it pulls the proc name and params for my libs all droopys but the minizip i loose the paramaters and am only left with the procname )

its driving me mad :shock:

Any help much appreciated

Thanks in advance

Zebuddi :D

Re: File format of the user libs ?

Posted: Sat May 05, 2012 3:20 pm
by ts-soft
the Compilerway: (works only in ascii)

Code: Select all

EnableExplicit

Procedure.s GetFunctionNames(List Functions.s())
  Protected.s Text, result, tmp
  Protected.i Compiler = RunProgram(#PB_Compiler_Home + "Compilers\pbcompiler", "/STANDBY", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
  Protected PureBasicVersion.s
  
  If Compiler
    If IsProgram(Compiler)
      Repeat
        tmp = ReadProgramString(compiler)
        If Left(tmp, 8) = "STARTING"
          PureBasicVersion = Trim(Right(tmp, Len(tmp) - 13))
        EndIf
      Until tmp = "READY"
      WriteProgramStringN(Compiler, "FUNCTIONLIST")
      
      Repeat
        Text = ReadProgramString(Compiler)
        If Text <> "OUTPUT" + #TAB$ + "COMPLETE"
          AddElement(Functions())
          Functions() = Trim(StringField(Text, 1, "("))
        EndIf
      Until Text = "OUTPUT" + #TAB$ + "COMPLETE"
      WriteProgramStringN(Compiler, "END")
      CloseProgram(Compiler)
    EndIf

    FirstElement(Functions()) 
    DeleteElement(Functions())
    ForEach Functions()
      result + Functions() + " "
    Next
  EndIf
  
  ProcedureReturn Trim(result)
EndProcedure

NewList Functions.s()

GetFunctionNames(Functions())

ForEach Functions()
  Debug Functions()
Next
The native way:

Code: Select all

EnableExplicit

Procedure GetAllLibFunc(Libname.s, Map FuncInfo.s())
  Protected size.i
  Protected file.i
  Protected buff.i
  Protected offset.i  
  Protected ende.i
  Protected i.l
  
  Protected LibFunc.s
  Protected LibDesc.s
  Protected LibParam.l
  Protected LibCount.l
  
  file = ReadFile(#PB_Any, Libname)
  
  If (file)
    size = Lof(file)
    buff = AllocateMemory(size)
    If (Not buff)
      ProcedureReturn 0
    EndIf    
    ReadData(file, buff, size)
    CloseFile(file)
  Else
    ProcedureReturn 0
  EndIf
  
  If (Not PeekS(buff + 8, 4, #PB_Ascii) = "3BIL")
    ProcedureReturn 0
  EndIf
  
  ende = PeekL(buff + 4) + 12

  offset = 20
  offset + Len(PeekS(buff + offset, -1, #PB_Ascii)) + 2

  LibCount = PeekB(buff + offset)
  
  If (LibCount)
    offset + 1
    
    For i = 0 To LibCount-1
      offset + Len(PeekS(buff + offset, -1, #PB_Ascii)) + 1
    Next
    
    offset + 1
  Else
    offset + 2
  EndIf

  offset + Len(PeekS(buff + offset, -1, #PB_Ascii)) + 1

  LibCount = PeekB(buff + offset)
  
  If (LibCount)
    offset + 1
    
    For i = 0 To LibCount-1
      offset + Len(PeekS(buff + offset, -1, #PB_Ascii) ) + 1
    Next
    
  Else
    offset + 1
  EndIf
    
  If (ende > offset)
    
    Repeat      
      
      LibFunc = PeekS(buff + offset, -1, #PB_Ascii)            
      offset + Len(LibFunc) + 1
      LibParam = PeekB(buff + offset)
      offset + 1
      
      If (LibParam)
        For i = 0 To LibParam-1
          offset + 1
        Next        
      EndIf
      
      offset + 4
      LibDesc = PeekS(buff + offset, -1, #PB_Ascii)
      offset + Len(LibDesc) + 1

      FuncInfo(LCase(LibFunc)) = LibDesc
      
    Until (ende <= offset)
    
  EndIf
 
EndProcedure

NewMap FuncInfo.s()
GetAllLibFunc(#PB_Compiler_Home + "PureLibraries\Gadget", FuncInfo())

ForEach FuncInfo()
  Debug MapKey(FuncInfo()) + FuncInfo()
Next

Greetings - Thomas

Re: File format of the user libs ?

Posted: Sun May 06, 2012 6:50 pm
by Zebuddi123
@Thomas

Thank you very much. That`s spot on, it would be nice to see the code the compiler actually uses.

Is there a way for the compiler version to actually pull the libname also ?

again thank you very much.

Zebuddi. :D

Re: File format of the user libs ?

Posted: Sun May 06, 2012 7:21 pm
by ts-soft
Read the documentation:

Code: Select all

RunProgram(#PB_Compiler_Home + "SDK\CompilerInterface.txt")
Greetings - Thomas

Re: File format of the user libs ?

Posted: Sun May 06, 2012 7:45 pm
by skywalk
Hi ts-soft,
Is there a similar way to read the Constants and Values and Structures and Fields from the various Residents files?
I would like to programmatically link constants to specific commands and verify my own constants don't 'step on' existing values. The Structure Viewer is too painful to use. Slow and does not export all. Only 1 at a time :(

Re: File format of the user libs ?

Posted: Sun May 06, 2012 8:42 pm
by ts-soft
I can only help you on Structure and Members:

Code: Select all

EnableExplicit

Structure strucMember
  Name.s
  List Members.s()
EndStructure

Structure strucName
  List Name.strucMember()
EndStructure


Procedure GetStructures(*p.strucName)
  Protected.i Compiler = RunProgram(#PB_Compiler_Home + "Compilers\pbcompiler", "/STANDBY", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
  Protected.s tmp, Text
  
  If Compiler
    If IsProgram(Compiler)
      Repeat
        tmp = ReadProgramString(compiler)
      Until tmp = "READY"
      WriteProgramStringN(Compiler, "STRUCTURELIST")
      Repeat
        Text = ReadProgramString(Compiler)
        If Text <> "OUTPUT" + #TAB$ + "COMPLETE"
          AddElement(*p\Name())
          *p\Name()\Name = Text
        EndIf
      Until Text = "OUTPUT" + #TAB$ + "COMPLETE"
      FirstElement(*p\Name())
      DeleteElement(*p\Name())
      ForEach *p\Name()
        WriteProgramStringN(Compiler, "STRUCTURE" + #TAB$ + *p\Name()\Name)
        Repeat
          Text = ReadProgramString(Compiler)
          If Text <> "OUTPUT" + #TAB$ + "COMPLETE"
            AddElement(*p\Name()\Members())
            *p\Name()\Members() = Text
          EndIf
        Until Text = "OUTPUT" + #TAB$ + "COMPLETE"        
      Next
      WriteProgramStringN(Compiler, "END")
      CloseProgram(Compiler)
    EndIf
  EndIf 
EndProcedure

Define.strucName structs
GetStructures(@structs)
With structs
  ForEach \Name()
    Debug "Structure " + \Name()\Name
    ForEach \Name()\Members()
      Debug "   " + \Name()\Members()
    Next
    Debug "EndStructure"
    Debug ""
  Next
EndWith
have fun :wink:

Re: File format of the user libs ?

Posted: Sun May 06, 2012 9:48 pm
by skywalk
Thanks ts-soft! That is very cool 8)

Re: File format of the user libs ?

Posted: Mon May 07, 2012 1:59 pm
by Danilo
ts-soft wrote:I can only help you on Structure and Members:
Get informations about Structures, Interfaces, and Procedures:

GetPBInfo.pb:

Code: Select all

CompilerIf #PB_Compiler_Unicode
    CompilerError "Please turn off compiler option 'Create unicode executable'"
CompilerEndIf


EnableExplicit

#Compiler = #PB_Compiler_Home+"compilers\pbcompiler.exe"

Procedure StartCompiler()
    ProcedureReturn RunProgram(#Compiler,"/STANDBY","",#PB_Program_Open|#PB_Program_Read|#PB_Program_Write|#PB_Program_Hide)
EndProcedure

Procedure StopCompiler(compiler)
    WriteProgramStringN(compiler, "END")
    WaitProgram(compiler,5000)
    CloseProgram(compiler)
EndProcedure

Procedure SendCompilerCommand(compiler,command$)
    If ProgramRunning(compiler)
        WriteProgramStringN(compiler, command$)
    EndIf
EndProcedure

Procedure.s GetCompilerOutput(compiler)
    If AvailableProgramOutput(compiler)
        ProcedureReturn ReadProgramString(compiler)
    EndIf
EndProcedure

Procedure FillList(compiler,List out.s(),space=0)
    Protected out$
    Protected space$=Space(space)
    While out$<>"OUTPUT"+#TAB$+"COMPLETE" And Left(out$,5)<>"ERROR"
        out$=GetCompilerOutput(compiler)
        If out$ And out$<>"OUTPUT"+#TAB$+"COMPLETE" And Left(out$,5)<>"ERROR" And FindString("0123456789",Mid(out$,1,1))=0
            AddElement(out())
            out()=space$+out$
        EndIf
    Wend
EndProcedure

Procedure GetStructureList(compiler,List out.s())
    If ProgramRunning(compiler)
        SendCompilerCommand(compiler,"STRUCTURELIST")
        FillList(compiler,out())
    EndIf
EndProcedure

Procedure GetProcedureList(compiler,List out.s())
    If ProgramRunning(compiler)
        SendCompilerCommand(compiler,"FUNCTIONLIST")
        FillList(compiler,out())
    EndIf
EndProcedure

Procedure GetInterfaceList(compiler,List out.s())
    If ProgramRunning(compiler)
        SendCompilerCommand(compiler,"INTERFACELIST")
        FillList(compiler,out())
    EndIf
EndProcedure

Procedure GetStructureInfo(compiler,struct$,List out.s())
    If ProgramRunning(compiler)
        SendCompilerCommand(compiler,"STRUCTURE"+#TAB$+struct$)
        FillList(compiler,out(),4)
    EndIf
EndProcedure

Procedure GetInterfaceInfo(compiler,interf$,List out.s())
    If ProgramRunning(compiler)
        SendCompilerCommand(compiler,"INTERFACE"+#TAB$+interf$)
        FillList(compiler,out(),4)
    EndIf
EndProcedure


Procedure WaitCompilerReady(compiler)
    Protected out$
    While out$<>"READY" And Left(out$,5)<>"ERROR"
        out$ = GetCompilerOutput(compiler)
        If out$
            Debug out$
        EndIf
    Wend
EndProcedure

Define  pb, out$
NewList structures.s()
NewList procedures.s()
NewList interfaces.s()

NewList structureInfo.s()
NewList interfaceInfo.s()

pb = StartCompiler()
If pb
    WaitCompilerReady(pb)

    GetStructureList(pb,structures())
    Debug "found "+Str(ListSize(structures()))+" structures"

    GetProcedureList(pb,procedures())
    Debug "found "+Str(ListSize(procedures()))+" procedures"

    GetInterfaceList(pb,interfaces())
    Debug "found "+Str(ListSize(interfaces()))+" interfaces"

    ClearList(structureInfo())
    ForEach structures()
        AddElement(structureInfo())
        structureInfo()="Structure "+structures()
        GetStructureInfo(pb,structures(),structureInfo())
        AddElement(structureInfo())
        structureInfo()="EndStructure"
        AddElement(structureInfo())
        structureInfo()=""
    Next

    ClearList(interfaceInfo())
    ForEach interfaces()
        AddElement(interfaceInfo())
        interfaceInfo()="Interface "+interfaces()
        GetInterfaceInfo(pb,interfaces(),interfaceInfo())
        AddElement(interfaceInfo())
        interfaceInfo()="EndInterface"
        AddElement(interfaceInfo())
        interfaceInfo()=""
    Next

    If CreateFile(0,GetPathPart(ProgramFilename())+"Structures.pb")
        ForEach structureInfo()
            WriteStringN(0,structureInfo())
        Next
        CloseFile(0)
    EndIf

    If CreateFile(0,GetPathPart(ProgramFilename())+"Interfaces.pb")
        ForEach interfaceInfo()
            WriteStringN(0,interfaceInfo())
        Next
        CloseFile(0)
    EndIf

    If CreateFile(0,GetPathPart(ProgramFilename())+"Procedures.pb")
        ForEach procedures()
            WriteStringN(0,procedures())
        Next
        CloseFile(0)
    EndIf

    
    StopCompiler(pb)
    Debug "Finish."
EndIf
Writes the files 'Structures.pb', 'Interfaces.pb', and 'Procedures.pb' at the end. Change it to what you need.

Re: File format of the user libs ?

Posted: Sun Sep 02, 2012 3:22 pm
by yrreti
Hi Danilo and ts-soft
I may be a little late from when this was posted, as I just noticed this topic when I was
searching for something. But I wanted to thank you for sharing your code on how to get
this information. Works nice.