448 lines
11 KiB
Text
448 lines
11 KiB
Text
|
' Gambas module file
|
||
|
|
||
|
Private $sRoot As String
|
||
|
Private $sComponent As String
|
||
|
Private $bVerbose As Boolean
|
||
|
|
||
|
Private Sub PrintError(sErr As String)
|
||
|
|
||
|
Error File.Name(Args[0]); ": error: "; sErr
|
||
|
Quit 1
|
||
|
|
||
|
End
|
||
|
|
||
|
Private Sub PrintMessage(sMsg As String)
|
||
|
|
||
|
If Not $bVerbose Then Return
|
||
|
Error sMsg
|
||
|
|
||
|
End
|
||
|
|
||
|
Public Sub Main()
|
||
|
|
||
|
Dim iInd As Integer, aSources As New String[]
|
||
|
Dim sArg, sRec As String, aRec As String[]
|
||
|
Dim sPath As String
|
||
|
Dim hOut As File
|
||
|
Dim bOnlySources As Boolean
|
||
|
Dim sMsg As String
|
||
|
|
||
|
$sRoot = System.Path
|
||
|
|
||
|
For iInd = 1 To Args.Max
|
||
|
Select Case Args[iInd]
|
||
|
Case "-h", "--help"
|
||
|
Print File.Load("usage")
|
||
|
Quit
|
||
|
Case "-V", "--version"
|
||
|
Print Application.Version
|
||
|
Quit
|
||
|
Case "-L", "--license"
|
||
|
Print File.Load("license")
|
||
|
Quit
|
||
|
Case "-v", "--verbose"
|
||
|
$bVerbose = True
|
||
|
Case "-r", "--root"
|
||
|
$sRoot = Args[iInd + 1]
|
||
|
If Not $sRoot Then PrintError(Args[iInd] & " requires an argument")
|
||
|
Inc iInd
|
||
|
Case "-c", "--component"
|
||
|
$sComponent = Args[iInd + 1]
|
||
|
If Not $sComponent Then PrintError(Args[iInd] & " requires an argument")
|
||
|
Inc iInd
|
||
|
Case "--"
|
||
|
bOnlySources = True
|
||
|
Default
|
||
|
If Not bOnlySources Then
|
||
|
If Args[iInd] Begins "-" Then
|
||
|
PrintError("unknown option: " & Args[iInd])
|
||
|
Endif
|
||
|
Endif
|
||
|
aSources.Add(Args[iInd])
|
||
|
End Select
|
||
|
Next
|
||
|
|
||
|
If aSources.Count = 0 Then aSources.Add(".")
|
||
|
|
||
|
If $sComponent Then
|
||
|
sPath = $sRoot &/ "share/gambas" & System.Version &/ "info" &/ $sComponent & ".help"
|
||
|
PrintMessage("Output to " & sPath)
|
||
|
hOut = Open sPath For Create
|
||
|
Else
|
||
|
hOut = File.Out
|
||
|
Endif
|
||
|
|
||
|
For Each sArg In aSources
|
||
|
If Left(sArg) <> "/" Then
|
||
|
If sArg = "." Then
|
||
|
sArg = Application.Dir
|
||
|
Else
|
||
|
sArg = Application.Dir &/ sArg
|
||
|
Endif
|
||
|
Endif
|
||
|
If IsDir(sArg) Then
|
||
|
aRec = RDir(sArg, "*.{c,cc,cpp}")
|
||
|
For Each sRec In aRec
|
||
|
OneFile(sArg &/ sRec, hOut)
|
||
|
Next
|
||
|
Else
|
||
|
OneFile(sArg, hOut)
|
||
|
Endif
|
||
|
Next
|
||
|
|
||
|
If $sComponent Then
|
||
|
Close #hOut
|
||
|
If Stat(sPath).Size = 0 Then
|
||
|
PrintMessage("Removing void data file")
|
||
|
Try Kill sPath
|
||
|
Endif
|
||
|
Endif
|
||
|
|
||
|
Catch
|
||
|
|
||
|
sMsg = Error.Text & ": " & Error.Backtrace.Join(" ")
|
||
|
Output To Default
|
||
|
PrintError(sMsg)
|
||
|
|
||
|
End
|
||
|
|
||
|
Private Sub AddHelp(cHelp As Collection, sClass As String, sSymbol As String, sHelp As String)
|
||
|
|
||
|
Dim cCol As Collection
|
||
|
|
||
|
PrintMessage("AddHelp: " & sClass & "." & sSymbol)
|
||
|
|
||
|
cCol = cHelp[sClass]
|
||
|
If Not cCol Then
|
||
|
cCol = New Collection
|
||
|
cHelp[sClass] = cCol
|
||
|
Endif
|
||
|
|
||
|
cCol[sSymbol] = sHelp
|
||
|
|
||
|
End
|
||
|
|
||
|
|
||
|
Private Sub OneFile(sPath As String, hOut As File)
|
||
|
|
||
|
Dim hFile As File
|
||
|
Dim sLine As String
|
||
|
Dim aHelp As New String[]
|
||
|
Dim bInsideComments As Boolean
|
||
|
Dim sHelp As String
|
||
|
Dim iPos As Integer
|
||
|
Dim bInsideDesc As Boolean
|
||
|
Dim sMacro As String
|
||
|
Dim iPos2 As Integer
|
||
|
Dim aArg As String[]
|
||
|
Dim sClass As String
|
||
|
Dim sSymbol As String
|
||
|
Dim cHelp As Collection
|
||
|
Dim sDeclareClass As String
|
||
|
Dim cCol As Variant
|
||
|
Dim aClass As String[]
|
||
|
Dim sImpl As String
|
||
|
|
||
|
PrintMessage("Processing " & sPath & "...")
|
||
|
hFile = Open sPath For Input
|
||
|
|
||
|
cHelp = New Collection
|
||
|
|
||
|
For Each sLine In hFile.Lines
|
||
|
|
||
|
sLine = Trim(sLine)
|
||
|
If Not sLine Then Continue
|
||
|
|
||
|
'PrintMessage(sLine)
|
||
|
|
||
|
If sLine Begins "/// " Then
|
||
|
|
||
|
aHelp.Add(Mid$(sLine, 5))
|
||
|
Continue
|
||
|
|
||
|
Else If sLine = "/**G" Or If sLine = "/**" Then
|
||
|
|
||
|
bInsideComments = True
|
||
|
Continue
|
||
|
|
||
|
Else If sLine Begins "/** " Then
|
||
|
|
||
|
aHelp.Add(Mid$(sLine, 5))
|
||
|
bInsideComments = True
|
||
|
Continue
|
||
|
|
||
|
Else If bInsideComments Then
|
||
|
|
||
|
If RTrim(sLine) Ends "*/" Then
|
||
|
|
||
|
bInsideComments = False
|
||
|
Continue
|
||
|
|
||
|
Else
|
||
|
|
||
|
While Left(sLine) = "*"
|
||
|
sLine = Mid$(sLine, 2)
|
||
|
Wend
|
||
|
If Left(sLine) = " " Then sLine = Mid$(sLine, 2)
|
||
|
aHelp.Add(sLine)
|
||
|
Continue
|
||
|
|
||
|
Endif
|
||
|
|
||
|
Endif
|
||
|
|
||
|
If aHelp.Count Then
|
||
|
|
||
|
sHelp = Trim(aHelp[0])
|
||
|
If Len(sHelp) >= 3 And If sHelp Begins "[" And If sHelp Ends "]" Then
|
||
|
sHelp = Mid$(sHelp, 2, -1)
|
||
|
iPos = InStr(sHelp, ".")
|
||
|
If iPos = 0 Then
|
||
|
sClass = sHelp
|
||
|
sSymbol = ""
|
||
|
Else
|
||
|
sClass = Left$(sHelp, iPos - 1)
|
||
|
sSymbol = Mid$(sHelp, iPos + 1)
|
||
|
Endif
|
||
|
|
||
|
aHelp.Remove(0)
|
||
|
AddHelp(cHelp, sClass, sSymbol, aHelp.Join("\n"))
|
||
|
sHelp = ""
|
||
|
Else
|
||
|
sHelp = Trim(aHelp.Join("\n"))
|
||
|
Endif
|
||
|
aHelp.Clear
|
||
|
|
||
|
Endif
|
||
|
|
||
|
If sHelp Then
|
||
|
If sLine Begins "BEGIN_METHOD" Or If sLine Begins "BEGIN_PROPERTY" Then
|
||
|
|
||
|
iPos = InStr(sLine, "(")
|
||
|
If iPos = 0 Then Continue
|
||
|
sLine = Mid$(sLine, iPos + 1)
|
||
|
iPos = InStr(sLine, ",")
|
||
|
If iPos = 0 Then iPos = InStr(sLine, ")")
|
||
|
If iPos = 0 Then Continue
|
||
|
sLine = Left(sLine, iPos - 1)
|
||
|
|
||
|
AddHelp(cHelp, "@", sLine, sHelp)
|
||
|
sHelp = ""
|
||
|
Continue
|
||
|
|
||
|
Endif
|
||
|
Endif
|
||
|
|
||
|
If sLine Begins "GB_DECLARE" Then
|
||
|
bInsideDesc = True
|
||
|
Try sDeclareClass = Scan(sLine, "GB_DECLARE*(\"*\"*")[1]
|
||
|
If Error Then PrintError("Missing class name in GB_DECLARE macro: " & sLine)
|
||
|
Continue
|
||
|
Endif
|
||
|
|
||
|
If bInsideDesc Then
|
||
|
|
||
|
If sLine Begins "GB_END_DECLARE" Then
|
||
|
bInsideDesc = False
|
||
|
Continue
|
||
|
Endif
|
||
|
|
||
|
|
||
|
iPos = InStr(sLine, "(")
|
||
|
If iPos = 0 Then Continue
|
||
|
sMacro = Left(sLine, iPos - 1)
|
||
|
|
||
|
If sMacro Not Begins "GB_" Then Continue
|
||
|
If InStr(sMacro, "_CONSTANT") = 0 And If InStr(sMacro, "_PROPERTY") = 0 And If InStr(sMacro, "_METHOD") = 0 Then Continue
|
||
|
|
||
|
iPos2 = InStr(sLine, ")", iPos + 1)
|
||
|
If iPos2 = 0 Then Continue
|
||
|
|
||
|
aArg = Split(Mid$(sLine, iPos + 1, iPos2 - iPos - 1), ",", Chr$(34))
|
||
|
sSymbol = Trim(aArg[0])
|
||
|
Try sImpl = Trim(aArg[2])
|
||
|
|
||
|
If sHelp Then
|
||
|
|
||
|
AddHelp(cHelp, sDeclareClass, sSymbol, sHelp)
|
||
|
sHelp = ""
|
||
|
|
||
|
Else
|
||
|
|
||
|
If InStr(sMacro, "_CONSTANT") Then Continue
|
||
|
If InStr(sMacro, "_SELF") Then Continue
|
||
|
Try sHelp = cHelp["@"][sImpl]
|
||
|
If sHelp Then
|
||
|
AddHelp(cHelp, sDeclareClass, sSymbol, sHelp)
|
||
|
sHelp = ""
|
||
|
Endif
|
||
|
|
||
|
Endif
|
||
|
|
||
|
Endif
|
||
|
|
||
|
Next
|
||
|
|
||
|
Close #hFile
|
||
|
|
||
|
' Make class list
|
||
|
|
||
|
aClass = New String[]
|
||
|
For Each cCol In cHelp
|
||
|
If cHelp.Key = "@" Then Continue
|
||
|
aClass.Add(cHelp.Key)
|
||
|
Next
|
||
|
aClass.Sort(gb.IgnoreCase)
|
||
|
|
||
|
' Generate help
|
||
|
|
||
|
For Each sClass In aClass
|
||
|
|
||
|
cCol = cHelp[sClass]
|
||
|
If cCol.Count = 0 Then Continue
|
||
|
|
||
|
Print #hOut, "#"; sClass
|
||
|
|
||
|
For Each sHelp In cCol
|
||
|
Print #hOut, cCol.Key
|
||
|
Print #hOut, "'"; Split(sHelp, "\n").Join("\n'")
|
||
|
Next
|
||
|
|
||
|
Next
|
||
|
|
||
|
End
|
||
|
|
||
|
' Private Function Extract(hFile As File) As String[]
|
||
|
'
|
||
|
' Dim hNameFn As New RegExp, hNameInline As New RegExp
|
||
|
' Dim sLine As String, sInline As String
|
||
|
' Dim aRes As New String[]
|
||
|
' Dim bRecord As Boolean
|
||
|
'
|
||
|
' hNameFn.Compile("^BEGIN_.*\\(([^,)]+).*")
|
||
|
' hNameInline.Compile("/\\*\\*G (.+)$")
|
||
|
'
|
||
|
' For Each sLine In hFile.Lines
|
||
|
' If sLine Match "^[\\t ]*\\*?\\*/$" Then
|
||
|
' If sInline Then
|
||
|
' aRes.Add("G " & sInline)
|
||
|
' sInline = ""
|
||
|
' bRecord = False
|
||
|
' Endif
|
||
|
' Continue
|
||
|
' Endif
|
||
|
' hNameFn.Exec(sLine)
|
||
|
' If hNameFn.Offset <> -1 And If bRecord And If Not sInline Then
|
||
|
' aRes.Add(hNameFn[1].Text)
|
||
|
' bRecord = False
|
||
|
' Endif
|
||
|
'
|
||
|
' If bRecord Then aRes.Add(RegExp.Replace(sLine, "^[\\t ]*\\*", "'"))
|
||
|
'
|
||
|
' If sLine Match "^/\\*\\*G$" Then
|
||
|
' If bRecord Then aRes.Add("ERROR")
|
||
|
' sInline = ""
|
||
|
' bRecord = True
|
||
|
' Endif
|
||
|
' hNameInline.Exec(sLine)
|
||
|
' If hNameInline.Offset <> -1 Then
|
||
|
' If bRecord Then aRes.Add("ERROR")
|
||
|
' sInline = LTrim$(hNameInline[1].Text)
|
||
|
' bRecord = True
|
||
|
' Endif
|
||
|
' Next
|
||
|
' If bRecord Then aRes.Add("ERROR")
|
||
|
' Return aRes
|
||
|
' End
|
||
|
'
|
||
|
' Private Function Translate(aSource As String[], sPath As String) As String[]
|
||
|
'
|
||
|
' Dim sLine As String, aRes As New String[]
|
||
|
'
|
||
|
' For Each sLine In aSource
|
||
|
' If Not sLine Then Continue
|
||
|
' If sLine = "ERROR" Or If sLine Begins "'" Then
|
||
|
' aRes.Add(sLine)
|
||
|
' Continue
|
||
|
' Endif
|
||
|
' If sLine Begins "G " Then ' Syntax-2?
|
||
|
' aRes.Add(Right$(sLine, -2))
|
||
|
' Continue
|
||
|
' Endif
|
||
|
' ' Syntax-1
|
||
|
' aRes.Add(GetSyntax1(sLine, sPath))
|
||
|
' Next
|
||
|
' Return aRes
|
||
|
' End
|
||
|
'
|
||
|
' Private Function GetSyntax1(sFunc As String, sPath As String) As String
|
||
|
'
|
||
|
' Dim hClassName As New RegExp, hFunction As New RegExp
|
||
|
' Dim hFile As File, sLine, sClass As String
|
||
|
' Dim aRes As New String[]
|
||
|
'
|
||
|
' hClassName.Compile("GB_DECLARE\\(\\\"([^\\\"]+).*")
|
||
|
' hFunction.Compile("GB_[^(]+\\(\\\"([^\"]+)\\\".*" & sFunc & "\\W")
|
||
|
'
|
||
|
' hFile = Open sPath For Input
|
||
|
' sClass = "ERROR"
|
||
|
' For Each sLine In hFile.Lines
|
||
|
' If Not sLine Then Continue
|
||
|
' hClassName.Exec(sLine)
|
||
|
' If hClassName.Offset <> -1 Then sClass = hClassName[1].Text
|
||
|
' hFunction.Exec(sLine)
|
||
|
' If hFunction.Offset <> -1 Then
|
||
|
' If Not aRes.Count Then aRes.Add(sClass)
|
||
|
' aRes.Add(hFunction[1].Text)
|
||
|
' Endif
|
||
|
' Next
|
||
|
' Close #hFile
|
||
|
' Return aRes.Join(" ")
|
||
|
' End
|
||
|
'
|
||
|
' Public Sub MakeHelp(aSource As String[], hOut As File)
|
||
|
'
|
||
|
' Dim sLine, sCls, sSym As String
|
||
|
' Dim cHelp As New Collection, aCurrent As New String[]
|
||
|
' Dim cClass As Collection, aHelp, aSyn As String[]
|
||
|
' Dim iInd As Integer
|
||
|
'
|
||
|
' Output To hOut
|
||
|
' For Each sLine In aSource
|
||
|
' If Not sLine Then Continue
|
||
|
' If sLine Begins "'" Then
|
||
|
' aCurrent.Add(sLine)
|
||
|
' Else
|
||
|
' With Scan(sLine, "* *")
|
||
|
' If .Count = 0 Then ' <Class>
|
||
|
' sCls = sLine
|
||
|
' sSym = "#"
|
||
|
' Else If .Count = 2 Then ' <Class> <Symbol-and-Synonym-List>
|
||
|
' sCls = Trim$(.[0])
|
||
|
' sSym = Trim$(.[1])
|
||
|
' Endif
|
||
|
' If Not cHelp[sCls] Then cHelp[sCls] = New Collection
|
||
|
' cHelp[sCls][sSym] = aCurrent
|
||
|
' aCurrent = New String[]
|
||
|
' End With
|
||
|
' Endif
|
||
|
' Next
|
||
|
'
|
||
|
' For Each cClass In cHelp
|
||
|
' Print "#"; cHelp.Key
|
||
|
' aHelp = cClass["#"]
|
||
|
' If aHelp Then Print aHelp.Join("\n")
|
||
|
' For Each aHelp In cClass
|
||
|
' If cClass.Key = "#" Then Continue
|
||
|
' aSyn = Split(cClass.Key, " ")
|
||
|
' Print aSyn[0]
|
||
|
' If aHelp.Count Then Print aHelp.Join("\n")
|
||
|
' For iInd = 1 To aSyn.Max
|
||
|
' Print aSyn[iInd]
|
||
|
' Print "' A synonym for";; aSyn[0]; "."
|
||
|
' Next
|
||
|
' Next
|
||
|
' Next
|
||
|
' Output To Default
|
||
|
' End
|